Merge remote-tracking branch 'official/master'

This commit is contained in:
Michalis Adamidis
2014-08-06 01:29:56 +02:00
114 changed files with 2756 additions and 1106 deletions

View File

@@ -1006,6 +1006,18 @@ namespace MediaBrowser.Controller.Entities
private BaseItem FindLinkedChild(LinkedChild info)
{
if (!string.IsNullOrWhiteSpace(info.ItemName))
{
if (string.Equals(info.ItemType, "musicgenre", StringComparison.OrdinalIgnoreCase))
{
return LibraryManager.GetMusicGenre(info.ItemName);
}
if (string.Equals(info.ItemType, "musicartist", StringComparison.OrdinalIgnoreCase))
{
return LibraryManager.GetArtist(info.ItemName);
}
}
if (!string.IsNullOrEmpty(info.Path))
{
var itemByPath = LibraryManager.RootFolder.FindByPath(info.Path);
@@ -1028,7 +1040,10 @@ namespace MediaBrowser.Controller.Entities
{
if (info.ItemYear.HasValue)
{
return info.ItemYear.Value == (i.ProductionYear ?? -1);
if (info.ItemYear.Value != (i.ProductionYear ?? -1))
{
return false;
}
}
return true;
}

View File

@@ -7,11 +7,6 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public abstract class BasePluginFolder : Folder, ICollectionFolder, IByReferenceItem
{
protected BasePluginFolder()
{
DisplayMediaType = "CollectionFolder";
}
public virtual string CollectionType
{
get { return null; }

View File

@@ -38,6 +38,12 @@ namespace MediaBrowser.Controller.Entities
Tags = new List<string>();
}
[IgnoreDataMember]
public virtual bool IsPreSorted
{
get { return false; }
}
/// <summary>
/// Gets a value indicating whether this instance is folder.
/// </summary>
@@ -855,7 +861,7 @@ namespace MediaBrowser.Controller.Entities
/// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
/// <returns>IEnumerable{BaseItem}.</returns>
/// <exception cref="System.ArgumentNullException"></exception>
public IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = true)
public virtual IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = true)
{
if (user == null)
{

View File

@@ -18,6 +18,15 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
[IgnoreDataMember]
public Guid? ItemId { get; set; }
public static LinkedChild Create(BaseItem item)
{
return new LinkedChild
{
Path = item.Path,
Type = LinkedChildType.Manual
};
}
}
public enum LinkedChildType

View File

@@ -1,4 +1,5 @@
using MediaBrowser.Common.Progress;
using System.Runtime.Serialization;
using MediaBrowser.Common.Progress;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
@@ -58,6 +59,15 @@ namespace MediaBrowser.Controller.Entities.Movies
return config.BlockUnratedItems.Contains(UnratedItem.Movie);
}
[IgnoreDataMember]
public override bool IsPreSorted
{
get
{
return true;
}
}
public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
{
var children = base.GetChildren(user, includeLinkedChildren);

View File

@@ -29,6 +29,15 @@ namespace MediaBrowser.Controller.Entities.TV
}
}
[IgnoreDataMember]
public override bool IsPreSorted
{
get
{
return true;
}
}
/// <summary>
/// We want to group into our Series
/// </summary>

View File

@@ -39,6 +39,15 @@ namespace MediaBrowser.Controller.Entities.TV
DisplaySpecialsWithSeasons = true;
}
[IgnoreDataMember]
public override bool IsPreSorted
{
get
{
return true;
}
}
public bool DisplaySpecialsWithSeasons { get; set; }
public List<Guid> LocalTrailerIds { get; set; }

View File

@@ -1,7 +1,6 @@
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Model.Entities;
using MoreLinq;
using System;
using System.Collections.Generic;
using System.Linq;

View File

@@ -303,8 +303,6 @@ namespace MediaBrowser.Controller.Library
}
else
{
logger.Debug("Evaluating series file: {0}", child.FullName);
var fullName = child.FullName;
if (EntityResolutionHelper.IsVideoFile(fullName) || EntityResolutionHelper.IsVideoPlaceHolder(fullName))

View File

@@ -217,6 +217,9 @@
<Compile Include="Notifications\UserNotification.cs" />
<Compile Include="Persistence\IFileOrganizationRepository.cs" />
<Compile Include="Persistence\MediaStreamQuery.cs" />
<Compile Include="Playlists\IPlaylistManager.cs" />
<Compile Include="Playlists\Playlist.cs" />
<Compile Include="Playlists\PlaylistCreationOptions.cs" />
<Compile Include="Providers\DirectoryService.cs" />
<Compile Include="Providers\ICustomMetadataProvider.cs" />
<Compile Include="Providers\IExternalId.cs" />

View File

@@ -0,0 +1,47 @@
using MediaBrowser.Controller.Entities;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Playlists
{
public interface IPlaylistManager
{
/// <summary>
/// Gets the playlists.
/// </summary>
/// <param name="userId">The user identifier.</param>
/// <returns>IEnumerable&lt;Playlist&gt;.</returns>
IEnumerable<Playlist> GetPlaylists(string userId);
/// <summary>
/// Creates the playlist.
/// </summary>
/// <param name="options">The options.</param>
/// <returns>Task&lt;Playlist&gt;.</returns>
Task<Playlist> CreatePlaylist(PlaylistCreationOptions options);
/// <summary>
/// Adds to playlist.
/// </summary>
/// <param name="playlistId">The playlist identifier.</param>
/// <param name="itemIds">The item ids.</param>
/// <returns>Task.</returns>
Task AddToPlaylist(string playlistId, IEnumerable<string> itemIds);
/// <summary>
/// Removes from playlist.
/// </summary>
/// <param name="playlistId">The playlist identifier.</param>
/// <param name="indeces">The indeces.</param>
/// <returns>Task.</returns>
Task RemoveFromPlaylist(string playlistId, IEnumerable<int> indeces);
/// <summary>
/// Gets the playlists folder.
/// </summary>
/// <param name="userId">The user identifier.</param>
/// <returns>Folder.</returns>
Folder GetPlaylistsFolder(string userId);
}
}

View File

@@ -0,0 +1,87 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
namespace MediaBrowser.Controller.Playlists
{
public class Playlist : Folder
{
public string OwnerUserId { get; set; }
public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
{
return GetPlayableItems(user);
}
public override IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = true)
{
return GetPlayableItems(user);
}
public IEnumerable<BaseItem> GetManageableItems()
{
return GetLinkedChildren();
}
private IEnumerable<BaseItem> GetPlayableItems(User user)
{
return GetPlaylistItems(MediaType, base.GetChildren(user, true), user);
}
public static IEnumerable<BaseItem> GetPlaylistItems(string playlistMediaType, IEnumerable<BaseItem> inputItems, User user)
{
return inputItems.SelectMany(i =>
{
var folder = i as Folder;
if (folder != null)
{
var items = folder.GetRecursiveChildren(user, true)
.Where(m => !m.IsFolder && string.Equals(m.MediaType, playlistMediaType, StringComparison.OrdinalIgnoreCase));
if (!folder.IsPreSorted)
{
items = LibraryManager.Sort(items, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending);
}
return items;
}
return new[] { i };
});
}
[IgnoreDataMember]
public override bool IsPreSorted
{
get
{
return true;
}
}
public string PlaylistMediaType { get; set; }
public override string MediaType
{
get
{
return PlaylistMediaType;
}
}
public void SetMediaType(string value)
{
PlaylistMediaType = value;
}
public override bool IsVisible(User user)
{
return base.IsVisible(user) && string.Equals(user.Id.ToString("N"), OwnerUserId);
}
}
}

View File

@@ -0,0 +1,20 @@
using System.Collections.Generic;
namespace MediaBrowser.Controller.Playlists
{
public class PlaylistCreationOptions
{
public string Name { get; set; }
public List<string> ItemIdList { get; set; }
public string MediaType { get; set; }
public string UserId { get; set; }
public PlaylistCreationOptions()
{
ItemIdList = new List<string>();
}
}
}

View File

@@ -1283,6 +1283,67 @@ namespace MediaBrowser.Controller.Providers
return new[] { personInfo };
}
protected LinkedChild GetLinkedChild(XmlReader reader)
{
reader.MoveToContent();
var linkedItem = new LinkedChild
{
Type = LinkedChildType.Manual
};
while (reader.Read())
{
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.Name)
{
case "Name":
{
linkedItem.ItemName = reader.ReadElementContentAsString();
break;
}
case "Path":
{
linkedItem.Path = reader.ReadElementContentAsString();
break;
}
case "Type":
{
linkedItem.ItemType = reader.ReadElementContentAsString();
break;
}
case "Year":
{
var val = reader.ReadElementContentAsString();
if (!string.IsNullOrWhiteSpace(val))
{
int rval;
if (int.TryParse(val, NumberStyles.Integer, _usCulture, out rval))
{
linkedItem.ItemYear = rval;
}
}
break;
}
default:
reader.Skip();
break;
}
}
}
return string.IsNullOrWhiteSpace(linkedItem.ItemName) || string.IsNullOrWhiteSpace(linkedItem.ItemType) ? null : linkedItem;
}
/// <summary>
/// Used to split names of comma or pipe delimeted genres and people
/// </summary>