diff options
Diffstat (limited to 'MediaBrowser.Controller/Entities')
42 files changed, 942 insertions, 965 deletions
diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs index e8ebbdb70..2105ef907 100644 --- a/MediaBrowser.Controller/Entities/AggregateFolder.cs +++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs @@ -20,19 +20,7 @@ namespace MediaBrowser.Controller.Entities { public AggregateFolder() { - PhysicalLocationsList = new List<string>(); - } - - /// <summary> - /// We don't support manual shortcuts - /// </summary> - [IgnoreDataMember] - protected override bool SupportsShortcutChildren - { - get - { - return false; - } + PhysicalLocationsList = EmptyStringArray; } [IgnoreDataMember] @@ -70,7 +58,7 @@ namespace MediaBrowser.Controller.Entities } [IgnoreDataMember] - public override IEnumerable<string> PhysicalLocations + public override string[] PhysicalLocations { get { @@ -78,23 +66,23 @@ namespace MediaBrowser.Controller.Entities } } - public List<string> PhysicalLocationsList { get; set; } + public string[] PhysicalLocationsList { get; set; } - protected override IEnumerable<FileSystemMetadata> GetFileSystemChildren(IDirectoryService directoryService) + protected override FileSystemMetadata[] GetFileSystemChildren(IDirectoryService directoryService) { return CreateResolveArgs(directoryService, true).FileSystemChildren; } - private List<Guid> _childrenIds = null; + private Guid[] _childrenIds = null; private readonly object _childIdsLock = new object(); protected override List<BaseItem> LoadChildren() { lock (_childIdsLock) { - if (_childrenIds == null || _childrenIds.Count == 0) + if (_childrenIds == null || _childrenIds.Length == 0) { - var list = base.LoadChildren().ToList(); - _childrenIds = list.Select(i => i.Id).ToList(); + var list = base.LoadChildren(); + _childrenIds = list.Select(i => i.Id).ToArray(); return list; } @@ -117,9 +105,9 @@ namespace MediaBrowser.Controller.Entities if (!changed) { - var locations = PhysicalLocations.ToList(); + var locations = PhysicalLocations; - var newLocations = CreateResolveArgs(new DirectoryService(Logger, FileSystem), false).PhysicalLocations.ToList(); + var newLocations = CreateResolveArgs(new DirectoryService(Logger, FileSystem), false).PhysicalLocations; if (!locations.SequenceEqual(newLocations)) { @@ -160,24 +148,22 @@ namespace MediaBrowser.Controller.Entities // When resolving the root, we need it's grandchildren (children of user views) var flattenFolderDepth = isPhysicalRoot ? 2 : 0; - var fileSystemDictionary = FileData.GetFilteredFileSystemEntries(directoryService, args.Path, FileSystem, Logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: isPhysicalRoot || args.IsVf); + var files = FileData.GetFilteredFileSystemEntries(directoryService, args.Path, FileSystem, Logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: isPhysicalRoot || args.IsVf); // Need to remove subpaths that may have been resolved from shortcuts // Example: if \\server\movies exists, then strip out \\server\movies\action if (isPhysicalRoot) { - var paths = LibraryManager.NormalizeRootPathList(fileSystemDictionary.Values); - - fileSystemDictionary = paths.ToDictionary(i => i.FullName); + files = LibraryManager.NormalizeRootPathList(files).ToArray(); } - args.FileSystemDictionary = fileSystemDictionary; + args.FileSystemChildren = files; } _requiresRefresh = _requiresRefresh || !args.PhysicalLocations.SequenceEqual(PhysicalLocations); if (setPhysicalLocations) { - PhysicalLocationsList = args.PhysicalLocations.ToList(); + PhysicalLocationsList = args.PhysicalLocations; } return args; @@ -226,7 +212,14 @@ namespace MediaBrowser.Controller.Entities throw new ArgumentNullException("id"); } - return _virtualChildren.FirstOrDefault(i => i.Id == id); + foreach (var child in _virtualChildren) + { + if (child.Id == id) + { + return child; + } + } + return null; } } } diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index 873ac3104..3ebf4da00 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -9,6 +9,7 @@ using System.Globalization; using System.Linq; using System.Threading; using MediaBrowser.Common.Extensions; +using MediaBrowser.Controller.Persistence; using MediaBrowser.Model.Serialization; namespace MediaBrowser.Controller.Entities.Audio @@ -27,9 +28,11 @@ namespace MediaBrowser.Controller.Entities.Audio /// Gets or sets the artist. /// </summary> /// <value>The artist.</value> - public List<string> Artists { get; set; } + [IgnoreDataMember] + public string[] Artists { get; set; } - public List<string> AlbumArtists { get; set; } + [IgnoreDataMember] + public string[] AlbumArtists { get; set; } [IgnoreDataMember] public override bool EnableRefreshOnDateModifiedChange @@ -39,8 +42,8 @@ namespace MediaBrowser.Controller.Entities.Audio public Audio() { - Artists = new List<string>(); - AlbumArtists = new List<string>(); + Artists = EmptyStringArray; + AlbumArtists = EmptyStringArray; } public override double? GetDefaultPrimaryImageAspectRatio() @@ -95,13 +98,23 @@ namespace MediaBrowser.Controller.Entities.Audio } [IgnoreDataMember] - public List<string> AllArtists + public string[] AllArtists { get { - var list = AlbumArtists.ToList(); + var list = new string[AlbumArtists.Length + Artists.Length]; - list.AddRange(Artists); + var index = 0; + foreach (var artist in AlbumArtists) + { + list[index] = artist; + index++; + } + foreach (var artist in Artists) + { + list[index] = artist; + index++; + } return list; @@ -157,7 +170,7 @@ namespace MediaBrowser.Controller.Entities.Audio songKey = Album + "-" + songKey; } - var albumArtist = AlbumArtists.FirstOrDefault(); + var albumArtist = AlbumArtists.Length == 0 ? null : AlbumArtists[0]; if (!string.IsNullOrWhiteSpace(albumArtist)) { songKey = albumArtist + "-" + songKey; @@ -193,6 +206,23 @@ namespace MediaBrowser.Controller.Entities.Audio return base.GetBlockUnratedType(); } + public List<MediaStream> GetMediaStreams() + { + return MediaSourceManager.GetMediaStreams(new MediaStreamQuery + { + ItemId = Id + }); + } + + public List<MediaStream> GetMediaStreams(MediaStreamType type) + { + return MediaSourceManager.GetMediaStreams(new MediaStreamQuery + { + ItemId = Id, + Type = type + }); + } + public SongInfo GetLookupInfo() { var info = GetItemLookupInfo<SongInfo>(); @@ -204,7 +234,7 @@ namespace MediaBrowser.Controller.Entities.Audio return info; } - public virtual IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution) + public virtual List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution) { if (SourceType == SourceType.Channel) { @@ -248,7 +278,7 @@ namespace MediaBrowser.Controller.Entities.Audio { Id = i.Id.ToString("N"), Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File, - MediaStreams = MediaSourceManager.GetMediaStreams(i.Id).ToList(), + MediaStreams = MediaSourceManager.GetMediaStreams(i.Id), Name = i.Name, Path = enablePathSubstituion ? GetMappedPath(i, i.Path, locationType) : i.Path, RunTimeTicks = i.RunTimeTicks, diff --git a/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs b/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs index a7c914664..b2dedada4 100644 --- a/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs @@ -1,25 +1,15 @@ -using MediaBrowser.Controller.Library; -using System.Collections.Generic; - + namespace MediaBrowser.Controller.Entities.Audio { public interface IHasAlbumArtist { - List<string> AlbumArtists { get; set; } + string[] AlbumArtists { get; set; } } public interface IHasArtist { - List<string> AllArtists { get; } - - List<string> Artists { get; set; } - } + string[] AllArtists { get; } - public static class HasArtistExtensions - { - public static bool HasAnyArtist(this IHasArtist hasArtist, string artist) - { - return NameExtensions.EqualsAny(hasArtist.AllArtists, artist); - } + string[] Artists { get; set; } } } diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index 516ab5053..7af8161ca 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -10,7 +10,6 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Dto; namespace MediaBrowser.Controller.Entities.Audio { @@ -19,13 +18,13 @@ namespace MediaBrowser.Controller.Entities.Audio /// </summary> public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo<AlbumInfo>, IMetadataContainer { - public List<string> AlbumArtists { get; set; } - public List<string> Artists { get; set; } + public string[] AlbumArtists { get; set; } + public string[] Artists { get; set; } public MusicAlbum() { - Artists = new List<string>(); - AlbumArtists = new List<string>(); + Artists = EmptyStringArray; + AlbumArtists = EmptyStringArray; } [IgnoreDataMember] @@ -48,17 +47,22 @@ namespace MediaBrowser.Controller.Entities.Audio public MusicArtist GetMusicArtist(DtoOptions options) { - var artist = GetParents().OfType<MusicArtist>().FirstOrDefault(); - - if (artist == null) + var parents = GetParents(); + foreach (var parent in parents) { - var name = AlbumArtist; - if (!string.IsNullOrWhiteSpace(name)) + var artist = parent as MusicArtist; + if (artist != null) { - artist = LibraryManager.GetArtist(name, options); + return artist; } } - return artist; + + var name = AlbumArtist; + if (!string.IsNullOrWhiteSpace(name)) + { + return LibraryManager.GetArtist(name, options); + } + return null; } [IgnoreDataMember] @@ -80,23 +84,32 @@ namespace MediaBrowser.Controller.Entities.Audio } [IgnoreDataMember] - public List<string> AllArtists + public string[] AllArtists { get { - var list = AlbumArtists.ToList(); + var list = new string[AlbumArtists.Length + Artists.Length]; - list.AddRange(Artists); + var index = 0; + foreach (var artist in AlbumArtists) + { + list[index] = artist; + index++; + } + foreach (var artist in Artists) + { + list[index] = artist; + index++; + } return list; - } } [IgnoreDataMember] public string AlbumArtist { - get { return AlbumArtists.FirstOrDefault(); } + get { return AlbumArtists.Length == 0 ? null : AlbumArtists[0]; } } [IgnoreDataMember] @@ -110,11 +123,11 @@ namespace MediaBrowser.Controller.Entities.Audio /// </summary> /// <value>The tracks.</value> [IgnoreDataMember] - public IEnumerable<Audio> Tracks + public IEnumerable<BaseItem> Tracks { get { - return GetRecursiveChildren(i => i is Audio).Cast<Audio>(); + return GetRecursiveChildren(i => i is Audio); } } @@ -200,7 +213,7 @@ namespace MediaBrowser.Controller.Entities.Audio public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken) { - var items = GetRecursiveChildren().ToList(); + var items = GetRecursiveChildren(); var totalItems = items.Count; var numComplete = 0; @@ -239,27 +252,22 @@ namespace MediaBrowser.Controller.Entities.Audio private async Task RefreshArtists(MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken) { - var artists = AllArtists.Select(i => + var all = AllArtists; + foreach (var i in all) { // This should not be necessary but we're seeing some cases of it if (string.IsNullOrWhiteSpace(i)) { - return null; + continue; } var artist = LibraryManager.GetArtist(i); if (!artist.IsAccessedByName) { - return null; + continue; } - return artist; - - }).Where(i => i != null).ToList(); - - foreach (var artist in artists) - { await artist.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); } } diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index 7a37b2e02..19fe68e25 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -212,20 +212,21 @@ namespace MediaBrowser.Controller.Entities.Audio public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken) { - var items = GetRecursiveChildren().ToList(); + var items = GetRecursiveChildren(); - var songs = items.OfType<Audio>().ToList(); - - var others = items.Except(songs).ToList(); - - var totalItems = songs.Count + others.Count; + var totalItems = items.Count; var numComplete = 0; var childUpdateType = ItemUpdateType.None; // Refresh songs - foreach (var item in songs) + foreach (var item in items) { + if (!(item is Audio)) + { + continue; + } + cancellationToken.ThrowIfCancellationRequested(); var updateType = await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); @@ -248,8 +249,13 @@ namespace MediaBrowser.Controller.Entities.Audio await RefreshMetadata(parentRefreshOptions, cancellationToken).ConfigureAwait(false); // Refresh all non-songs - foreach (var item in others) + foreach (var item in items) { + if (item is Audio) + { + continue; + } + cancellationToken.ThrowIfCancellationRequested(); var updateType = await item.RefreshMetadata(parentRefreshOptions, cancellationToken).ConfigureAwait(false); diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs index d4a85b4d0..02e652048 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using MediaBrowser.Model.Serialization; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Extensions; diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 6f8d62c0c..c41d3e0cd 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -25,6 +25,7 @@ using System.Threading.Tasks; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Extensions; using MediaBrowser.Controller.IO; +using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Globalization; @@ -39,20 +40,26 @@ namespace MediaBrowser.Controller.Entities /// <summary> /// Class BaseItem /// </summary> - public abstract class BaseItem : IHasProviderIds, IHasImages, IHasUserData, IHasMetadata, IHasLookupInfo<ItemLookupInfo> + public abstract class BaseItem : IHasMetadata, IHasLookupInfo<ItemLookupInfo> { + protected static Guid[] EmptyGuidArray = new Guid[] { }; + protected static MetadataFields[] EmptyMetadataFieldsArray = new MetadataFields[] { }; + protected static string[] EmptyStringArray = new string[] { }; + protected static MediaUrl[] EmptyMediaUrlArray = new MediaUrl[] { }; + protected static ItemImageInfo[] EmptyItemImageInfoArray = new ItemImageInfo[] { }; + public static readonly LinkedChild[] EmptyLinkedChildArray = new LinkedChild[] { }; + protected BaseItem() { - ThemeSongIds = new List<Guid>(); - ThemeVideoIds = new List<Guid>(); - Tags = new List<string>(); + ThemeSongIds = EmptyGuidArray; + ThemeVideoIds = EmptyGuidArray; + Tags = EmptyStringArray; Genres = new List<string>(); - Studios = new List<string>(); + Studios = EmptyStringArray; ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - LockedFields = new List<MetadataFields>(); - ImageInfos = new List<ItemImageInfo>(); - InheritedTags = new List<string>(); - ProductionLocations = new List<string>(); + LockedFields = EmptyMetadataFieldsArray; + ImageInfos = EmptyItemImageInfoArray; + ProductionLocations = EmptyStringArray; } public static readonly char[] SlugReplaceChars = { '?', '/', '&' }; @@ -73,8 +80,10 @@ namespace MediaBrowser.Controller.Entities public static string ThemeSongFilename = "theme"; public static string ThemeVideosFolderName = "backdrops"; - public List<Guid> ThemeSongIds { get; set; } - public List<Guid> ThemeVideoIds { get; set; } + [IgnoreDataMember] + public Guid[] ThemeSongIds { get; set; } + [IgnoreDataMember] + public Guid[] ThemeVideoIds { get; set; } [IgnoreDataMember] public string PreferredMetadataCountryCode { get; set; } @@ -87,7 +96,8 @@ namespace MediaBrowser.Controller.Entities [IgnoreDataMember] public string Tagline { get; set; } - public List<ItemImageInfo> ImageInfos { get; set; } + [IgnoreDataMember] + public ItemImageInfo[] ImageInfos { get; set; } [IgnoreDataMember] public bool IsVirtualItem { get; set; } @@ -129,12 +139,6 @@ namespace MediaBrowser.Controller.Entities public bool IsInMixedFolder { get; set; } [IgnoreDataMember] - protected virtual bool SupportsIsInMixedFolderDetection - { - get { return false; } - } - - [IgnoreDataMember] public virtual bool SupportsPlayedStatus { get @@ -152,16 +156,6 @@ namespace MediaBrowser.Controller.Entities } } - public bool DetectIsInMixedFolder() - { - if (SupportsIsInMixedFolderDetection) - { - - } - - return IsInMixedFolder; - } - [IgnoreDataMember] public virtual bool SupportsRemoteImageDownloading { @@ -193,27 +187,14 @@ namespace MediaBrowser.Controller.Entities } [IgnoreDataMember] - public string SlugName - { - get - { - var name = Name; - if (string.IsNullOrWhiteSpace(name)) - { - return string.Empty; - } - - return SlugReplaceChars.Aggregate(name, (current, c) => current.Replace(c, SlugChar)); - } - } - - [IgnoreDataMember] public bool IsUnaired { get { return PremiereDate.HasValue && PremiereDate.Value.ToLocalTime().Date >= DateTime.Now.Date; } } + [IgnoreDataMember] public int? TotalBitrate { get; set; } + [IgnoreDataMember] public ExtraType? ExtraType { get; set; } [IgnoreDataMember] @@ -541,6 +522,7 @@ namespace MediaBrowser.Controller.Entities public static ICollectionManager CollectionManager { get; set; } public static IImageProcessor ImageProcessor { get; set; } public static IMediaSourceManager MediaSourceManager { get; set; } + public static IMediaEncoder MediaEncoder { get; set; } /// <summary> /// Returns a <see cref="System.String" /> that represents this instance. @@ -559,7 +541,7 @@ namespace MediaBrowser.Controller.Entities /// </summary> /// <value>The locked fields.</value> [IgnoreDataMember] - public List<MetadataFields> LockedFields { get; set; } + public MetadataFields[] LockedFields { get; set; } /// <summary> /// Gets the type of the media. @@ -575,7 +557,7 @@ namespace MediaBrowser.Controller.Entities } [IgnoreDataMember] - public virtual IEnumerable<string> PhysicalLocations + public virtual string[] PhysicalLocations { get { @@ -667,27 +649,34 @@ namespace MediaBrowser.Controller.Entities } var sortable = Name.Trim().ToLower(); - sortable = ConfigurationManager.Configuration.SortRemoveCharacters.Aggregate(sortable, (current, search) => current.Replace(search.ToLower(), string.Empty)); - sortable = ConfigurationManager.Configuration.SortReplaceCharacters.Aggregate(sortable, (current, search) => current.Replace(search.ToLower(), " ")); + foreach (var removeChar in ConfigurationManager.Configuration.SortRemoveCharacters) + { + sortable = sortable.Replace(removeChar, string.Empty); + } + + foreach (var replaceChar in ConfigurationManager.Configuration.SortReplaceCharacters) + { + sortable = sortable.Replace(replaceChar, " "); + } foreach (var search in ConfigurationManager.Configuration.SortRemoveWords) { - var searchLower = search.ToLower(); // Remove from beginning if a space follows - if (sortable.StartsWith(searchLower + " ")) + if (sortable.StartsWith(search + " ")) { - sortable = sortable.Remove(0, searchLower.Length + 1); + sortable = sortable.Remove(0, search.Length + 1); } // Remove from middle if surrounded by spaces - sortable = sortable.Replace(" " + searchLower + " ", " "); + sortable = sortable.Replace(" " + search + " ", " "); // Remove from end if followed by a space - if (sortable.EndsWith(" " + searchLower)) + if (sortable.EndsWith(" " + search)) { - sortable = sortable.Remove(sortable.Length - (searchLower.Length + 1)); + sortable = sortable.Remove(sortable.Length - (search.Length + 1)); } } + return ModifySortChunks(sortable); } @@ -774,7 +763,15 @@ namespace MediaBrowser.Controller.Entities public T FindParent<T>() where T : Folder { - return GetParents().OfType<T>().FirstOrDefault(); + foreach (var parent in GetParents()) + { + var item = parent as T; + if (item != null) + { + return item; + } + } + return null; } [IgnoreDataMember] @@ -819,13 +816,6 @@ namespace MediaBrowser.Controller.Entities public DateTime? EndDate { get; set; } /// <summary> - /// Gets or sets the display type of the media. - /// </summary> - /// <value>The display type of the media.</value> - [IgnoreDataMember] - public string DisplayMediaType { get; set; } - - /// <summary> /// Gets or sets the official rating. /// </summary> /// <value>The official rating.</value> @@ -835,9 +825,6 @@ namespace MediaBrowser.Controller.Entities [IgnoreDataMember] public int InheritedParentalRatingValue { get; set; } - [IgnoreDataMember] - public List<string> InheritedTags { get; set; } - /// <summary> /// Gets or sets the critic rating. /// </summary> @@ -864,7 +851,7 @@ namespace MediaBrowser.Controller.Entities /// </summary> /// <value>The studios.</value> [IgnoreDataMember] - public List<string> Studios { get; set; } + public string[] Studios { get; set; } /// <summary> /// Gets or sets the genres. @@ -878,9 +865,10 @@ namespace MediaBrowser.Controller.Entities /// </summary> /// <value>The tags.</value> [IgnoreDataMember] - public List<string> Tags { get; set; } + public string[] Tags { get; set; } - public List<string> ProductionLocations { get; set; } + [IgnoreDataMember] + public string[] ProductionLocations { get; set; } /// <summary> /// Gets or sets the home page URL. @@ -989,11 +977,11 @@ namespace MediaBrowser.Controller.Entities /// Loads the theme songs. /// </summary> /// <returns>List{Audio.Audio}.</returns> - private static IEnumerable<Audio.Audio> LoadThemeSongs(List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService) + private static Audio.Audio[] LoadThemeSongs(List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService) { var files = fileSystemChildren.Where(i => i.IsDirectory) .Where(i => string.Equals(i.Name, ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase)) - .SelectMany(i => directoryService.GetFiles(i.FullName)) + .SelectMany(i => FileSystem.GetFiles(i.FullName)) .ToList(); // Support plex/xbmc convention @@ -1018,18 +1006,18 @@ namespace MediaBrowser.Controller.Entities return audio; // Sort them so that the list can be easily compared for changes - }).OrderBy(i => i.Path).ToList(); + }).OrderBy(i => i.Path).ToArray(); } /// <summary> /// Loads the video backdrops. /// </summary> /// <returns>List{Video}.</returns> - private static IEnumerable<Video> LoadThemeVideos(IEnumerable<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService) + private static Video[] LoadThemeVideos(IEnumerable<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService) { var files = fileSystemChildren.Where(i => i.IsDirectory) .Where(i => string.Equals(i.Name, ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase)) - .SelectMany(i => directoryService.GetFiles(i.FullName)); + .SelectMany(i => FileSystem.GetFiles(i.FullName)); return LibraryManager.ResolvePaths(files, directoryService, null, new LibraryOptions()) .OfType<Video>() @@ -1048,7 +1036,7 @@ namespace MediaBrowser.Controller.Entities return item; // Sort them so that the list can be easily compared for changes - }).OrderBy(i => i.Path).ToList(); + }).OrderBy(i => i.Path).ToArray(); } public Task RefreshMetadata(CancellationToken cancellationToken) @@ -1156,7 +1144,7 @@ namespace MediaBrowser.Controller.Entities { if (SupportsThemeMedia) { - if (!DetectIsInMixedFolder()) + if (!IsInMixedFolder) { themeSongsChanged = await RefreshThemeSongs(this, options, fileSystemChildren, cancellationToken).ConfigureAwait(false); @@ -1174,7 +1162,7 @@ namespace MediaBrowser.Controller.Entities return themeSongsChanged || themeVideosChanged || localTrailersChanged; } - protected virtual IEnumerable<FileSystemMetadata> GetFileSystemChildren(IDirectoryService directoryService) + protected virtual FileSystemMetadata[] GetFileSystemChildren(IDirectoryService directoryService) { var path = ContainingFolderPath; @@ -1185,7 +1173,7 @@ namespace MediaBrowser.Controller.Entities { var newItems = LibraryManager.FindTrailers(this, fileSystemChildren, options.DirectoryService).ToList(); - var newItemIds = newItems.Select(i => i.Id).ToList(); + var newItemIds = newItems.Select(i => i.Id).ToArray(); var itemsChanged = !item.LocalTrailerIds.SequenceEqual(newItemIds); @@ -1200,9 +1188,9 @@ namespace MediaBrowser.Controller.Entities private async Task<bool> RefreshThemeVideos(BaseItem item, MetadataRefreshOptions options, IEnumerable<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) { - var newThemeVideos = LoadThemeVideos(fileSystemChildren, options.DirectoryService).ToList(); + var newThemeVideos = LoadThemeVideos(fileSystemChildren, options.DirectoryService); - var newThemeVideoIds = newThemeVideos.Select(i => i.Id).ToList(); + var newThemeVideoIds = newThemeVideos.Select(i => i.Id).ToArray(newThemeVideos.Length); var themeVideosChanged = !item.ThemeVideoIds.SequenceEqual(newThemeVideoIds); @@ -1231,8 +1219,8 @@ namespace MediaBrowser.Controller.Entities /// </summary> private async Task<bool> RefreshThemeSongs(BaseItem item, MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) { - var newThemeSongs = LoadThemeSongs(fileSystemChildren, options.DirectoryService).ToList(); - var newThemeSongIds = newThemeSongs.Select(i => i.Id).ToList(); + var newThemeSongs = LoadThemeSongs(fileSystemChildren, options.DirectoryService); + var newThemeSongIds = newThemeSongs.Select(i => i.Id).ToArray(newThemeSongs.Length); var themeSongsChanged = !item.ThemeSongIds.SequenceEqual(newThemeSongIds); @@ -1260,6 +1248,7 @@ namespace MediaBrowser.Controller.Entities /// Gets or sets the provider ids. /// </summary> /// <value>The provider ids.</value> + [IgnoreDataMember] public Dictionary<string, string> ProviderIds { get; set; } [IgnoreDataMember] @@ -1311,12 +1300,9 @@ namespace MediaBrowser.Controller.Entities { var current = this; - if (!SupportsIsInMixedFolderDetection) + if (current.IsInMixedFolder != newItem.IsInMixedFolder) { - if (current.IsInMixedFolder != newItem.IsInMixedFolder) - { - return false; - } + return false; } return true; @@ -1737,12 +1723,28 @@ namespace MediaBrowser.Controller.Entities throw new ArgumentNullException("name"); } - if (!Studios.Contains(name, StringComparer.OrdinalIgnoreCase)) + var current = Studios; + + if (!current.Contains(name, StringComparer.OrdinalIgnoreCase)) { - Studios.Add(name); + if (current.Length == 0) + { + Studios = new[] { name }; + } + else + { + var list = current.ToArray(current.Length + 1); + list[list.Length - 1] = name; + Studios = list; + } } } + public void SetStudios(IEnumerable<string> names) + { + Studios = names.Distinct().ToArray(); + } + /// <summary> /// Adds a genre to the item /// </summary> @@ -1769,7 +1771,7 @@ namespace MediaBrowser.Controller.Entities /// <param name="resetPosition">if set to <c>true</c> [reset position].</param> /// <returns>Task.</returns> /// <exception cref="System.ArgumentNullException"></exception> - public virtual async Task MarkPlayed(User user, + public virtual void MarkPlayed(User user, DateTime? datePlayed, bool resetPosition) { @@ -1797,7 +1799,7 @@ namespace MediaBrowser.Controller.Entities data.LastPlayedDate = datePlayed ?? data.LastPlayedDate ?? DateTime.UtcNow; data.Played = true; - await UserDataManager.SaveUserData(user.Id, this, data, UserDataSaveReason.TogglePlayed, CancellationToken.None).ConfigureAwait(false); + UserDataManager.SaveUserData(user.Id, this, data, UserDataSaveReason.TogglePlayed, CancellationToken.None); } /// <summary> @@ -1806,7 +1808,7 @@ namespace MediaBrowser.Controller.Entities /// <param name="user">The user.</param> /// <returns>Task.</returns> /// <exception cref="System.ArgumentNullException"></exception> - public virtual async Task MarkUnplayed(User user) + public virtual void MarkUnplayed(User user) { if (user == null) { @@ -1823,7 +1825,7 @@ namespace MediaBrowser.Controller.Entities data.LastPlayedDate = null; data.Played = false; - await UserDataManager.SaveUserData(user.Id, this, data, UserDataSaveReason.TogglePlayed, CancellationToken.None).ConfigureAwait(false); + UserDataManager.SaveUserData(user.Id, this, data, UserDataSaveReason.TogglePlayed, CancellationToken.None); } /// <summary> @@ -1862,10 +1864,18 @@ namespace MediaBrowser.Controller.Entities if (existingImage != null) { - ImageInfos.Remove(existingImage); + existingImage.Path = image.Path; + existingImage.DateModified = image.DateModified; + existingImage.IsPlaceholder = image.IsPlaceholder; } - ImageInfos.Add(image); + else + { + var currentCount = ImageInfos.Length; + var newList = ImageInfos.ToArray(currentCount + 1); + newList[currentCount] = image; + ImageInfos = newList; + } } public void SetImagePath(ImageType type, int index, FileSystemMetadata file) @@ -1879,7 +1889,10 @@ namespace MediaBrowser.Controller.Entities if (image == null) { - ImageInfos.Add(GetImageInfo(file, type)); + var currentCount = ImageInfos.Length; + var newList = ImageInfos.ToArray(currentCount + 1); + newList[currentCount] = GetImageInfo(file, type); + ImageInfos = newList; } else { @@ -1920,7 +1933,12 @@ namespace MediaBrowser.Controller.Entities public void RemoveImage(ItemImageInfo image) { - ImageInfos.Remove(image); + RemoveImages(new List<ItemImageInfo> { image }); + } + + public void RemoveImages(List<ItemImageInfo> deletedImages) + { + ImageInfos = ImageInfos.Except(deletedImages).ToArray(); } public virtual Task UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken) @@ -1937,7 +1955,7 @@ namespace MediaBrowser.Controller.Entities .Where(i => i.IsLocalFile) .Select(i => FileSystem.GetDirectoryName(i.Path)) .Distinct(StringComparer.OrdinalIgnoreCase) - .SelectMany(directoryService.GetFilePaths) + .SelectMany(i => FileSystem.GetFilePaths(i)) .ToList(); var deletedImages = ImageInfos @@ -1946,7 +1964,7 @@ namespace MediaBrowser.Controller.Entities if (deletedImages.Count > 0) { - ImageInfos = ImageInfos.Except(deletedImages).ToList(); + ImageInfos = ImageInfos.Except(deletedImages).ToArray(); } return deletedImages.Count > 0; @@ -2066,10 +2084,25 @@ namespace MediaBrowser.Controller.Entities .Where(i => i.IsLocalFile && !newImagePaths.Contains(i.Path, StringComparer.OrdinalIgnoreCase) && !FileSystem.FileExists(i.Path)) .ToList(); - ImageInfos = ImageInfos.Except(deleted).ToList(); + if (deleted.Count > 0) + { + ImageInfos = ImageInfos.Except(deleted).ToArray(); + } } - ImageInfos.AddRange(newImageList.Select(i => GetImageInfo(i, imageType))); + if (newImageList.Count > 0) + { + var currentCount = ImageInfos.Length; + var newList = ImageInfos.ToArray(currentCount + newImageList.Count); + + foreach (var image in newImageList) + { + newList[currentCount] = GetImageInfo(image, imageType); + currentCount++; + } + + ImageInfos = newList; + } return newImageList.Count > 0; } @@ -2107,10 +2140,10 @@ namespace MediaBrowser.Controller.Entities } var filename = System.IO.Path.GetFileNameWithoutExtension(Path); - var extensions = new[] { ".nfo", ".xml", ".srt" }.ToList(); - extensions.AddRange(SupportedImageExtensionsList); + var extensions = new List<string> { ".nfo", ".xml", ".srt" }; + extensions.AddRange(SupportedImageExtensions); - return FileSystem.GetFiles(FileSystem.GetDirectoryName(Path), extensions.ToArray(), false, false) + return FileSystem.GetFiles(FileSystem.GetDirectoryName(Path), extensions.ToArray(extensions.Count), false, false) .Where(i => System.IO.Path.GetFileNameWithoutExtension(i.FullName).StartsWith(filename, StringComparison.OrdinalIgnoreCase)) .ToList(); } @@ -2234,7 +2267,7 @@ namespace MediaBrowser.Controller.Entities return path; } - public virtual void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user, List<ItemFields> fields) + public virtual void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user, ItemFields[] fields) { if (RunTimeTicks.HasValue) { @@ -2270,12 +2303,12 @@ namespace MediaBrowser.Controller.Entities if (!item.Studios.SequenceEqual(ownedItem.Studios, StringComparer.Ordinal)) { newOptions.ForceSave = true; - ownedItem.Studios = item.Studios.ToList(); + ownedItem.Studios = item.Studios; } if (!item.ProductionLocations.SequenceEqual(ownedItem.ProductionLocations, StringComparer.Ordinal)) { newOptions.ForceSave = true; - ownedItem.ProductionLocations = item.ProductionLocations.ToList(); + ownedItem.ProductionLocations = item.ProductionLocations; } if (item.CommunityRating != ownedItem.CommunityRating) { @@ -2334,7 +2367,9 @@ namespace MediaBrowser.Controller.Entities public string GetEtag(User user) { - return string.Join("|", GetEtagValues(user).ToArray()).GetMD5().ToString("N"); + var list = GetEtagValues(user); + + return string.Join("|", list.ToArray(list.Count)).GetMD5().ToString("N"); } protected virtual List<string> GetEtagValues(User user) @@ -2357,7 +2392,14 @@ namespace MediaBrowser.Controller.Entities return this; } - return GetParents().FirstOrDefault(i => i.IsTopParent); + foreach (var parent in GetParents()) + { + if (parent.IsTopParent) + { + return parent; + } + } + return null; } [IgnoreDataMember] diff --git a/MediaBrowser.Controller/Entities/Book.cs b/MediaBrowser.Controller/Entities/Book.cs index 7cb242589..9b1a52f83 100644 --- a/MediaBrowser.Controller/Entities/Book.cs +++ b/MediaBrowser.Controller/Entities/Book.cs @@ -1,7 +1,7 @@ using System; +using System.Linq; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; -using System.Linq; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Entities; diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index d88b7da34..537beb26b 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -27,17 +27,8 @@ namespace MediaBrowser.Controller.Entities public CollectionFolder() { - PhysicalLocationsList = new List<string>(); - PhysicalFolderIds = new List<Guid>(); - } - - [IgnoreDataMember] - protected override bool SupportsShortcutChildren - { - get - { - return true; - } + PhysicalLocationsList = EmptyStringArray; + PhysicalFolderIds = EmptyGuidArray; } [IgnoreDataMember] @@ -149,7 +140,7 @@ namespace MediaBrowser.Controller.Entities } [IgnoreDataMember] - public override IEnumerable<string> PhysicalLocations + public override string[] PhysicalLocations { get { @@ -162,10 +153,10 @@ namespace MediaBrowser.Controller.Entities return true; } - public List<string> PhysicalLocationsList { get; set; } - public List<Guid> PhysicalFolderIds { get; set; } + public string[] PhysicalLocationsList { get; set; } + public Guid[] PhysicalFolderIds { get; set; } - protected override IEnumerable<FileSystemMetadata> GetFileSystemChildren(IDirectoryService directoryService) + protected override FileSystemMetadata[] GetFileSystemChildren(IDirectoryService directoryService) { return CreateResolveArgs(directoryService, true).FileSystemChildren; } @@ -177,9 +168,9 @@ namespace MediaBrowser.Controller.Entities if (!changed) { - var locations = PhysicalLocations.ToList(); + var locations = PhysicalLocations; - var newLocations = CreateResolveArgs(new DirectoryService(Logger, FileSystem), false).PhysicalLocations.ToList(); + var newLocations = CreateResolveArgs(new DirectoryService(Logger, FileSystem), false).PhysicalLocations; if (!locations.SequenceEqual(newLocations)) { @@ -189,7 +180,7 @@ namespace MediaBrowser.Controller.Entities if (!changed) { - var folderIds = PhysicalFolderIds.ToList(); + var folderIds = PhysicalFolderIds; var newFolderIds = GetPhysicalFolders(false).Select(i => i.Id).ToList(); @@ -249,17 +240,17 @@ namespace MediaBrowser.Controller.Entities var changed = !linkedChildren.SequenceEqual(LinkedChildren, new LinkedChildComparer(FileSystem)); - LinkedChildren = linkedChildren; + LinkedChildren = linkedChildren.ToArray(linkedChildren.Count); - var folderIds = PhysicalFolderIds.ToList(); - var newFolderIds = physicalFolders.Select(i => i.Id).ToList(); + var folderIds = PhysicalFolderIds; + var newFolderIds = physicalFolders.Select(i => i.Id).ToArray(); if (!folderIds.SequenceEqual(newFolderIds)) { changed = true; if (setFolders) { - PhysicalFolderIds = newFolderIds.ToList(); + PhysicalFolderIds = newFolderIds; } } @@ -301,24 +292,22 @@ namespace MediaBrowser.Controller.Entities // When resolving the root, we need it's grandchildren (children of user views) var flattenFolderDepth = isPhysicalRoot ? 2 : 0; - var fileSystemDictionary = FileData.GetFilteredFileSystemEntries(directoryService, args.Path, FileSystem, Logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: isPhysicalRoot || args.IsVf); + var files = FileData.GetFilteredFileSystemEntries(directoryService, args.Path, FileSystem, Logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: isPhysicalRoot || args.IsVf); // Need to remove subpaths that may have been resolved from shortcuts // Example: if \\server\movies exists, then strip out \\server\movies\action if (isPhysicalRoot) { - var paths = LibraryManager.NormalizeRootPathList(fileSystemDictionary.Values); - - fileSystemDictionary = paths.ToDictionary(i => i.FullName); + files = LibraryManager.NormalizeRootPathList(files).ToArray(); } - args.FileSystemDictionary = fileSystemDictionary; + args.FileSystemChildren = files; } _requiresRefresh = _requiresRefresh || !args.PhysicalLocations.SequenceEqual(PhysicalLocations); if (setPhysicalLocations) { - PhysicalLocationsList = args.PhysicalLocations.ToList(); + PhysicalLocationsList = args.PhysicalLocations; } return args; diff --git a/MediaBrowser.Controller/Entities/Extensions.cs b/MediaBrowser.Controller/Entities/Extensions.cs index 5e792a03a..36855a86c 100644 --- a/MediaBrowser.Controller/Entities/Extensions.cs +++ b/MediaBrowser.Controller/Entities/Extensions.cs @@ -1,6 +1,7 @@ using MediaBrowser.Model.Entities; using System; using System.Linq; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Controller.Entities { @@ -12,11 +13,7 @@ namespace MediaBrowser.Controller.Entities /// <summary> /// Adds the trailer URL. /// </summary> - /// <param name="item">The item.</param> - /// <param name="url">The URL.</param> - /// <param name="isDirectLink">if set to <c>true</c> [is direct link].</param> - /// <exception cref="System.ArgumentNullException">url</exception> - public static void AddTrailerUrl(this IHasTrailers item, string url, bool isDirectLink) + public static void AddTrailerUrl(this IHasTrailers item, string url) { if (string.IsNullOrWhiteSpace(url)) { @@ -27,10 +24,22 @@ namespace MediaBrowser.Controller.Entities if (current == null) { - item.RemoteTrailers.Add(new MediaUrl + var mediaUrl = new MediaUrl { Url = url - }); + }; + + if (item.RemoteTrailers.Length == 0) + { + item.RemoteTrailers = new[] { mediaUrl }; + } + else + { + var list = item.RemoteTrailers.ToArray(item.RemoteTrailers.Length + 1); + list[list.Length - 1] = mediaUrl; + + item.RemoteTrailers = list; + } } } } diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 5d74cf218..2e741a8c4 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -20,6 +20,7 @@ using MediaBrowser.Controller.IO; using MediaBrowser.Model.Channels; using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Controller.Entities { @@ -37,14 +38,14 @@ namespace MediaBrowser.Controller.Entities /// <value><c>true</c> if this instance is root; otherwise, <c>false</c>.</value> public bool IsRoot { get; set; } - public virtual List<LinkedChild> LinkedChildren { get; set; } + public LinkedChild[] LinkedChildren { get; set; } [IgnoreDataMember] public DateTime? DateLastMediaAdded { get; set; } public Folder() { - LinkedChildren = new List<LinkedChild>(); + LinkedChildren = EmptyLinkedChildArray; } [IgnoreDataMember] @@ -185,7 +186,7 @@ namespace MediaBrowser.Controller.Entities /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> /// <exception cref="System.InvalidOperationException">Unable to add + item.Name</exception> - public async Task AddChild(BaseItem item, CancellationToken cancellationToken) + public void AddChild(BaseItem item, CancellationToken cancellationToken) { item.SetParent(this); @@ -208,7 +209,7 @@ namespace MediaBrowser.Controller.Entities item.DateModified = DateTime.UtcNow; } - await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false); + LibraryManager.CreateItem(item, cancellationToken); } /// <summary> @@ -468,7 +469,7 @@ namespace MediaBrowser.Controller.Entities } } - await LibraryManager.CreateItems(newItems, cancellationToken).ConfigureAwait(false); + LibraryManager.CreateItems(newItems, cancellationToken); } } else @@ -647,15 +648,15 @@ namespace MediaBrowser.Controller.Entities public static bool IsPathOffline(string path, List<string> allLibraryPaths) { - if (FileSystem.FileExists(path)) - { - return false; - } + //if (FileSystem.FileExists(path)) + //{ + // return false; + //} var originalPath = path; // Depending on whether the path is local or unc, it may return either null or '\' at the top - while (!string.IsNullOrEmpty(path) && path.Length > 1) + while (!string.IsNullOrWhiteSpace(path) && path.Length > 1) { if (FileSystem.DirectoryExists(path)) { @@ -706,11 +707,11 @@ namespace MediaBrowser.Controller.Entities public virtual int GetChildCount(User user) { - if (LinkedChildren.Count > 0) + if (LinkedChildren.Length > 0) { if (!(this is ICollectionFolder)) { - return GetChildren(user, true).Count(); + return GetChildren(user, true).Count; } } @@ -797,10 +798,10 @@ namespace MediaBrowser.Controller.Entities if (user != null) { // needed for boxsets - itemsList = itemsList.Where(i => i.IsVisibleStandalone(query.User)); + itemsList = itemsList.Where(i => i.IsVisibleStandalone(query.User)).ToList(); } - IEnumerable<BaseItem> returnItems; + BaseItem[] returnItems; int totalCount = 0; if (query.EnableTotalRecordCount) @@ -811,16 +812,16 @@ namespace MediaBrowser.Controller.Entities } else { - returnItems = itemsList; + returnItems = itemsList.ToArray(); } if (limit.HasValue) { - returnItems = returnItems.Skip(startIndex ?? 0).Take(limit.Value); + returnItems = returnItems.Skip(startIndex ?? 0).Take(limit.Value).ToArray(); } else if (startIndex.HasValue) { - returnItems = returnItems.Skip(startIndex.Value); + returnItems = returnItems.Skip(startIndex.Value).ToArray(); } return new QueryResult<BaseItem> @@ -843,7 +844,7 @@ namespace MediaBrowser.Controller.Entities private bool RequiresPostFiltering(InternalItemsQuery query) { - if (LinkedChildren.Count > 0) + if (LinkedChildren.Length > 0) { if (!(this is ICollectionFolder)) { @@ -921,12 +922,6 @@ namespace MediaBrowser.Controller.Entities return true; } - if (query.AirDays.Length > 0) - { - Logger.Debug("Query requires post-filtering due to AirDays"); - return true; - } - if (query.SeriesStatuses.Length > 0) { Logger.Debug("Query requires post-filtering due to SeriesStatuses"); @@ -957,7 +952,7 @@ namespace MediaBrowser.Controller.Entities { var result = LibraryManager.GetItemsResult(query); - if (query.SortBy.Length == 0) + if (query.OrderBy.Length == 0) { var ids = query.ItemIds.ToList(); @@ -970,6 +965,27 @@ namespace MediaBrowser.Controller.Entities return GetItemsInternal(query); } + public BaseItem[] GetItemList(InternalItemsQuery query) + { + query.EnableTotalRecordCount = false; + + if (query.ItemIds.Length > 0) + { + var result = LibraryManager.GetItemList(query); + + if (query.OrderBy.Length == 0) + { + var ids = query.ItemIds.ToList(); + + // Try to preserve order + return result.OrderBy(i => ids.IndexOf(i.Id.ToString("N"))).ToArray(); + } + return result.ToArray(result.Count); + } + + return GetItemsInternal(query).Items; + } + protected virtual QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query) { if (SourceType == SourceType.Channel) @@ -984,8 +1000,7 @@ namespace MediaBrowser.Controller.Entities Limit = query.Limit, StartIndex = query.StartIndex, UserId = query.User.Id.ToString("N"), - SortBy = query.SortBy, - SortOrder = query.SortOrder + OrderBy = query.OrderBy }, new SimpleProgress<double>(), CancellationToken.None).Result; } @@ -1028,7 +1043,7 @@ namespace MediaBrowser.Controller.Entities return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager, ConfigurationManager, collapseBoxSetItems, enableSorting); } - public virtual IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren) + public virtual List<BaseItem> GetChildren(User user, bool includeLinkedChildren) { if (user == null) { @@ -1042,7 +1057,7 @@ namespace MediaBrowser.Controller.Entities AddChildren(user, includeLinkedChildren, result, false, null); - return result.Values; + return result.Values.ToList(); } protected virtual IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user) @@ -1203,7 +1218,7 @@ namespace MediaBrowser.Controller.Entities return GetLinkedChildren(); } - if (LinkedChildren.Count == 0) + if (LinkedChildren.Length == 0) { return new List<BaseItem>(); } @@ -1292,14 +1307,9 @@ namespace MediaBrowser.Controller.Entities /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> protected virtual bool RefreshLinkedChildren(IEnumerable<FileSystemMetadata> fileSystemChildren) { - var currentManualLinks = LinkedChildren.Where(i => i.Type == LinkedChildType.Manual).ToList(); - var currentShortcutLinks = LinkedChildren.Where(i => i.Type == LinkedChildType.Shortcut).ToList(); - - List<LinkedChild> newShortcutLinks; - if (SupportsShortcutChildren) { - newShortcutLinks = fileSystemChildren + var newShortcutLinks = fileSystemChildren .Where(i => !i.IsDirectory && FileSystem.IsShortcut(i.FullName)) .Select(i => { @@ -1330,16 +1340,17 @@ namespace MediaBrowser.Controller.Entities }) .Where(i => i != null) .ToList(); - } - else { newShortcutLinks = new List<LinkedChild>(); } - if (!newShortcutLinks.SequenceEqual(currentShortcutLinks, new LinkedChildComparer(FileSystem))) - { - Logger.Info("Shortcut links have changed for {0}", Path); + var currentShortcutLinks = LinkedChildren.Where(i => i.Type == LinkedChildType.Shortcut).ToList(); - newShortcutLinks.AddRange(currentManualLinks); - LinkedChildren = newShortcutLinks; - return true; + if (!newShortcutLinks.SequenceEqual(currentShortcutLinks, new LinkedChildComparer(FileSystem))) + { + Logger.Info("Shortcut links have changed for {0}", Path); + + newShortcutLinks.AddRange(LinkedChildren.Where(i => i.Type == LinkedChildType.Manual)); + LinkedChildren = newShortcutLinks.ToArray(newShortcutLinks.Count); + return true; + } } foreach (var child in LinkedChildren) @@ -1358,7 +1369,7 @@ namespace MediaBrowser.Controller.Entities /// <param name="datePlayed">The date played.</param> /// <param name="resetPosition">if set to <c>true</c> [reset position].</param> /// <returns>Task.</returns> - public override async Task MarkPlayed(User user, + public override void MarkPlayed(User user, DateTime? datePlayed, bool resetPosition) { @@ -1370,17 +1381,18 @@ namespace MediaBrowser.Controller.Entities EnableTotalRecordCount = false }; - if (!user.Configuration.DisplayMissingEpisodes || !user.Configuration.DisplayUnairedEpisodes) + if (!user.Configuration.DisplayMissingEpisodes) { query.IsVirtualItem = false; } - var itemsResult = GetItems(query); + var itemsResult = GetItemList(query); // Sweep through recursively and update status - var tasks = itemsResult.Items.Select(c => c.MarkPlayed(user, datePlayed, resetPosition)); - - await Task.WhenAll(tasks).ConfigureAwait(false); + foreach (var item in itemsResult) + { + item.MarkPlayed(user, datePlayed, resetPosition); + } } /// <summary> @@ -1388,9 +1400,9 @@ namespace MediaBrowser.Controller.Entities /// </summary> /// <param name="user">The user.</param> /// <returns>Task.</returns> - public override async Task MarkUnplayed(User user) + public override void MarkUnplayed(User user) { - var itemsResult = GetItems(new InternalItemsQuery + var itemsResult = GetItemList(new InternalItemsQuery { User = user, Recursive = true, @@ -1400,14 +1412,15 @@ namespace MediaBrowser.Controller.Entities }); // Sweep through recursively and update status - var tasks = itemsResult.Items.Select(c => c.MarkUnplayed(user)); - - await Task.WhenAll(tasks).ConfigureAwait(false); + foreach (var item in itemsResult) + { + item.MarkUnplayed(user); + } } public override bool IsPlayed(User user) { - var itemsResult = GetItems(new InternalItemsQuery(user) + var itemsResult = GetItemList(new InternalItemsQuery(user) { Recursive = true, IsFolder = false, @@ -1416,7 +1429,7 @@ namespace MediaBrowser.Controller.Entities }); - return itemsResult.Items + return itemsResult .All(i => i.IsPlayed(user)); } @@ -1465,7 +1478,7 @@ namespace MediaBrowser.Controller.Entities } } - public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user, List<ItemFields> fields) + public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user, ItemFields[] fields) { if (!SupportsUserDataFromChildren) { diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs index baefc9dfa..a99058925 100644 --- a/MediaBrowser.Controller/Entities/Game.cs +++ b/MediaBrowser.Controller/Entities/Game.cs @@ -3,7 +3,6 @@ using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using System; using System.Collections.Generic; -using System.Linq; using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; @@ -13,14 +12,14 @@ namespace MediaBrowser.Controller.Entities { public Game() { - MultiPartGameFiles = new List<string>(); - RemoteTrailers = new List<MediaUrl>(); - LocalTrailerIds = new List<Guid>(); - RemoteTrailerIds = new List<Guid>(); + MultiPartGameFiles = EmptyStringArray; + RemoteTrailers = EmptyMediaUrlArray; + LocalTrailerIds = EmptyGuidArray; + RemoteTrailerIds = EmptyGuidArray; } - public List<Guid> LocalTrailerIds { get; set; } - public List<Guid> RemoteTrailerIds { get; set; } + public Guid[] LocalTrailerIds { get; set; } + public Guid[] RemoteTrailerIds { get; set; } public override bool CanDownload() { @@ -45,7 +44,7 @@ namespace MediaBrowser.Controller.Entities /// Gets or sets the remote trailers. /// </summary> /// <value>The remote trailers.</value> - public List<MediaUrl> RemoteTrailers { get; set; } + public MediaUrl[] RemoteTrailers { get; set; } /// <summary> /// Gets the type of the media. @@ -84,7 +83,7 @@ namespace MediaBrowser.Controller.Entities /// <summary> /// Holds the paths to the game files in the event this is a multipart game /// </summary> - public List<string> MultiPartGameFiles { get; set; } + public string[] MultiPartGameFiles { get; set; } public override List<string> GetUserDataKeys() { @@ -100,7 +99,7 @@ namespace MediaBrowser.Controller.Entities public override IEnumerable<FileSystemMetadata> GetDeletePaths() { - if (!DetectIsInMixedFolder()) + if (!IsInMixedFolder) { return new[] { new FileSystemMetadata @@ -127,16 +126,5 @@ namespace MediaBrowser.Controller.Entities return id; } - - /// <summary> - /// Gets the trailer ids. - /// </summary> - /// <returns>List<Guid>.</returns> - public List<Guid> GetTrailerIds() - { - var list = LocalTrailerIds.ToList(); - list.AddRange(RemoteTrailerIds); - return list; - } } } diff --git a/MediaBrowser.Controller/Entities/GameGenre.cs b/MediaBrowser.Controller/Entities/GameGenre.cs index 836020d88..4e78a7fa5 100644 --- a/MediaBrowser.Controller/Entities/GameGenre.cs +++ b/MediaBrowser.Controller/Entities/GameGenre.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using MediaBrowser.Model.Serialization; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Extensions; diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs index 4b70eae58..790f8938e 100644 --- a/MediaBrowser.Controller/Entities/Genre.cs +++ b/MediaBrowser.Controller/Entities/Genre.cs @@ -2,7 +2,6 @@ using MediaBrowser.Controller.Entities.Audio; using System; using System.Collections.Generic; -using System.Linq; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Extensions; using MediaBrowser.Model.Extensions; diff --git a/MediaBrowser.Controller/Entities/ICollectionFolder.cs b/MediaBrowser.Controller/Entities/ICollectionFolder.cs index d8b02034c..b70ad322d 100644 --- a/MediaBrowser.Controller/Entities/ICollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/ICollectionFolder.cs @@ -13,7 +13,7 @@ namespace MediaBrowser.Controller.Entities string Path { get; } string Name { get; } Guid Id { get; } - IEnumerable<string> PhysicalLocations { get; } + string[] PhysicalLocations { get; } } public interface ISupportsUserSpecificView diff --git a/MediaBrowser.Controller/Entities/IHasId.cs b/MediaBrowser.Controller/Entities/IHasId.cs deleted file mode 100644 index 9698adf7a..000000000 --- a/MediaBrowser.Controller/Entities/IHasId.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; - -namespace MediaBrowser.Controller.Entities -{ - public interface IHasId - { - Guid Id { get; } - } -} diff --git a/MediaBrowser.Controller/Entities/IHasImages.cs b/MediaBrowser.Controller/Entities/IHasImages.cs deleted file mode 100644 index e2b3c0777..000000000 --- a/MediaBrowser.Controller/Entities/IHasImages.cs +++ /dev/null @@ -1,264 +0,0 @@ -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; - -using MediaBrowser.Controller.IO; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.IO; - -namespace MediaBrowser.Controller.Entities -{ - public interface IHasImages : IHasProviderIds, IHasId - { - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - string Name { get; set; } - - /// <summary> - /// Gets the path. - /// </summary> - /// <value>The path.</value> - string Path { get; set; } - - /// <summary> - /// Gets the file name without extension. - /// </summary> - /// <value>The file name without extension.</value> - string FileNameWithoutExtension { get; } - - /// <summary> - /// Gets the type of the location. - /// </summary> - /// <value>The type of the location.</value> - LocationType LocationType { get; } - - /// <summary> - /// Gets the locked fields. - /// </summary> - /// <value>The locked fields.</value> - List<MetadataFields> LockedFields { get; } - - /// <summary> - /// Gets the images. - /// </summary> - /// <param name="imageType">Type of the image.</param> - /// <returns>IEnumerable{ItemImageInfo}.</returns> - IEnumerable<ItemImageInfo> GetImages(ImageType imageType); - - /// <summary> - /// Gets the image path. - /// </summary> - /// <param name="imageType">Type of the image.</param> - /// <param name="imageIndex">Index of the image.</param> - /// <returns>System.String.</returns> - string GetImagePath(ImageType imageType, int imageIndex); - - /// <summary> - /// Gets the image information. - /// </summary> - /// <param name="imageType">Type of the image.</param> - /// <param name="imageIndex">Index of the image.</param> - /// <returns>ItemImageInfo.</returns> - ItemImageInfo GetImageInfo(ImageType imageType, int imageIndex); - - /// <summary> - /// Sets the image. - /// </summary> - /// <param name="type">The type.</param> - /// <param name="index">The index.</param> - /// <param name="file">The file.</param> - void SetImagePath(ImageType type, int index, FileSystemMetadata file); - - /// <summary> - /// Determines whether the specified type has image. - /// </summary> - /// <param name="type">The type.</param> - /// <param name="imageIndex">Index of the image.</param> - /// <returns><c>true</c> if the specified type has image; otherwise, <c>false</c>.</returns> - bool HasImage(ImageType type, int imageIndex); - - /// <summary> - /// Allowses the multiple images. - /// </summary> - /// <param name="type">The type.</param> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> - bool AllowsMultipleImages(ImageType type); - - /// <summary> - /// Swaps the images. - /// </summary> - /// <param name="type">The type.</param> - /// <param name="index1">The index1.</param> - /// <param name="index2">The index2.</param> - /// <returns>Task.</returns> - Task SwapImages(ImageType type, int index1, int index2); - - /// <summary> - /// Gets the display type of the media. - /// </summary> - /// <value>The display type of the media.</value> - string DisplayMediaType { get; set; } - - /// <summary> - /// Gets or sets the primary image path. - /// </summary> - /// <value>The primary image path.</value> - string PrimaryImagePath { get; } - - /// <summary> - /// Gets the preferred metadata language. - /// </summary> - /// <returns>System.String.</returns> - string GetPreferredMetadataLanguage(); - - /// <summary> - /// Validates the images and returns true or false indicating if any were removed. - /// </summary> - bool ValidateImages(IDirectoryService directoryService); - - /// <summary> - /// Gets a value indicating whether this instance is owned item. - /// </summary> - /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> - bool IsOwnedItem { get; } - - /// <summary> - /// Gets the containing folder path. - /// </summary> - /// <value>The containing folder path.</value> - string ContainingFolderPath { get; } - - /// <summary> - /// Adds the images. - /// </summary> - /// <param name="imageType">Type of the image.</param> - /// <param name="images">The images.</param> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> - bool AddImages(ImageType imageType, List<FileSystemMetadata> images); - - /// <summary> - /// Determines whether [is save local metadata enabled]. - /// </summary> - /// <returns><c>true</c> if [is save local metadata enabled]; otherwise, <c>false</c>.</returns> - bool IsSaveLocalMetadataEnabled(); - - /// <summary> - /// Gets a value indicating whether [supports local metadata]. - /// </summary> - /// <value><c>true</c> if [supports local metadata]; otherwise, <c>false</c>.</value> - bool SupportsLocalMetadata { get; } - - bool DetectIsInMixedFolder(); - - /// <summary> - /// Gets a value indicating whether this instance is locked. - /// </summary> - /// <value><c>true</c> if this instance is locked; otherwise, <c>false</c>.</value> - bool IsLocked { get; } - - /// <summary> - /// Gets a value indicating whether [supports remote image downloading]. - /// </summary> - /// <value><c>true</c> if [supports remote image downloading]; otherwise, <c>false</c>.</value> - bool SupportsRemoteImageDownloading { get; } - - /// <summary> - /// Gets the internal metadata path. - /// </summary> - /// <returns>System.String.</returns> - string GetInternalMetadataPath(); - - /// <summary> - /// Gets a value indicating whether [always scan internal metadata path]. - /// </summary> - /// <value><c>true</c> if [always scan internal metadata path]; otherwise, <c>false</c>.</value> - bool AlwaysScanInternalMetadataPath { get; } - - /// <summary> - /// Determines whether [is internet metadata enabled]. - /// </summary> - /// <returns><c>true</c> if [is internet metadata enabled]; otherwise, <c>false</c>.</returns> - bool IsInternetMetadataEnabled(); - - /// <summary> - /// Removes the image. - /// </summary> - /// <param name="image">The image.</param> - void RemoveImage(ItemImageInfo image); - - /// <summary> - /// Updates to repository. - /// </summary> - /// <param name="updateReason">The update reason.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - Task UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken); - - /// <summary> - /// Sets the image. - /// </summary> - /// <param name="image">The image.</param> - /// <param name="index">The index.</param> - void SetImage(ItemImageInfo image, int index); - - double? GetDefaultPrimaryImageAspectRatio(); - - int? ProductionYear { get; set; } - } - - public static class HasImagesExtensions - { - /// <summary> - /// Gets the image path. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="imageType">Type of the image.</param> - /// <returns>System.String.</returns> - public static string GetImagePath(this IHasImages item, ImageType imageType) - { - return item.GetImagePath(imageType, 0); - } - - public static bool HasImage(this IHasImages item, ImageType imageType) - { - return item.HasImage(imageType, 0); - } - - /// <summary> - /// Sets the image path. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="imageType">Type of the image.</param> - /// <param name="file">The file.</param> - public static void SetImagePath(this IHasImages item, ImageType imageType, FileSystemMetadata file) - { - item.SetImagePath(imageType, 0, file); - } - - /// <summary> - /// Sets the image path. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="imageType">Type of the image.</param> - /// <param name="file">The file.</param> - public static void SetImagePath(this IHasImages item, ImageType imageType, string file) - { - if (file.StartsWith("http", System.StringComparison.OrdinalIgnoreCase)) - { - item.SetImage(new ItemImageInfo - { - Path = file, - Type = imageType - }, 0); - } - else - { - item.SetImagePath(imageType, BaseItem.FileSystem.GetFileInfo(file)); - } - } - } -} diff --git a/MediaBrowser.Controller/Entities/IHasMediaSources.cs b/MediaBrowser.Controller/Entities/IHasMediaSources.cs index 832b9f6c1..54786134f 100644 --- a/MediaBrowser.Controller/Entities/IHasMediaSources.cs +++ b/MediaBrowser.Controller/Entities/IHasMediaSources.cs @@ -1,15 +1,17 @@ using MediaBrowser.Model.Dto; using System.Collections.Generic; +using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Entities { - public interface IHasMediaSources : IHasUserData + public interface IHasMediaSources : IHasMetadata { /// <summary> /// Gets the media sources. /// </summary> /// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param> /// <returns>Task{IEnumerable{MediaSourceInfo}}.</returns> - IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution); + List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution); + List<MediaStream> GetMediaStreams(); } } diff --git a/MediaBrowser.Controller/Entities/IHasMetadata.cs b/MediaBrowser.Controller/Entities/IHasMetadata.cs index 62c67336c..59d9bd9f9 100644 --- a/MediaBrowser.Controller/Entities/IHasMetadata.cs +++ b/MediaBrowser.Controller/Entities/IHasMetadata.cs @@ -1,12 +1,18 @@ using System; using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.IO; namespace MediaBrowser.Controller.Entities { /// <summary> /// Interface IHasMetadata /// </summary> - public interface IHasMetadata : IHasImages + public interface IHasMetadata : IHasProviderIds, IHasUserData { /// <summary> /// Gets the preferred metadata country code. @@ -64,6 +70,253 @@ namespace MediaBrowser.Controller.Entities int? GetInheritedParentalRatingValue(); int InheritedParentalRatingValue { get; set; } List<string> GetInheritedTags(); - List<string> InheritedTags { get; set; } + long? RunTimeTicks { get; set; } + + /// <summary> + /// Gets the name. + /// </summary> + /// <value>The name.</value> + string Name { get; set; } + + /// <summary> + /// Gets the path. + /// </summary> + /// <value>The path.</value> + string Path { get; set; } + + /// <summary> + /// Gets the file name without extension. + /// </summary> + /// <value>The file name without extension.</value> + string FileNameWithoutExtension { get; } + + /// <summary> + /// Gets the type of the location. + /// </summary> + /// <value>The type of the location.</value> + LocationType LocationType { get; } + + /// <summary> + /// Gets the locked fields. + /// </summary> + /// <value>The locked fields.</value> + MetadataFields[] LockedFields { get; } + + /// <summary> + /// Gets the images. + /// </summary> + /// <param name="imageType">Type of the image.</param> + /// <returns>IEnumerable{ItemImageInfo}.</returns> + IEnumerable<ItemImageInfo> GetImages(ImageType imageType); + + /// <summary> + /// Gets the image path. + /// </summary> + /// <param name="imageType">Type of the image.</param> + /// <param name="imageIndex">Index of the image.</param> + /// <returns>System.String.</returns> + string GetImagePath(ImageType imageType, int imageIndex); + + /// <summary> + /// Gets the image information. + /// </summary> + /// <param name="imageType">Type of the image.</param> + /// <param name="imageIndex">Index of the image.</param> + /// <returns>ItemImageInfo.</returns> + ItemImageInfo GetImageInfo(ImageType imageType, int imageIndex); + + /// <summary> + /// Sets the image. + /// </summary> + /// <param name="type">The type.</param> + /// <param name="index">The index.</param> + /// <param name="file">The file.</param> + void SetImagePath(ImageType type, int index, FileSystemMetadata file); + + /// <summary> + /// Determines whether the specified type has image. + /// </summary> + /// <param name="type">The type.</param> + /// <param name="imageIndex">Index of the image.</param> + /// <returns><c>true</c> if the specified type has image; otherwise, <c>false</c>.</returns> + bool HasImage(ImageType type, int imageIndex); + + /// <summary> + /// Allowses the multiple images. + /// </summary> + /// <param name="type">The type.</param> + /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> + bool AllowsMultipleImages(ImageType type); + + /// <summary> + /// Swaps the images. + /// </summary> + /// <param name="type">The type.</param> + /// <param name="index1">The index1.</param> + /// <param name="index2">The index2.</param> + /// <returns>Task.</returns> + Task SwapImages(ImageType type, int index1, int index2); + + /// <summary> + /// Gets or sets the primary image path. + /// </summary> + /// <value>The primary image path.</value> + string PrimaryImagePath { get; } + + /// <summary> + /// Gets the preferred metadata language. + /// </summary> + /// <returns>System.String.</returns> + string GetPreferredMetadataLanguage(); + + /// <summary> + /// Validates the images and returns true or false indicating if any were removed. + /// </summary> + bool ValidateImages(IDirectoryService directoryService); + + /// <summary> + /// Gets a value indicating whether this instance is owned item. + /// </summary> + /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> + bool IsOwnedItem { get; } + + /// <summary> + /// Gets the containing folder path. + /// </summary> + /// <value>The containing folder path.</value> + string ContainingFolderPath { get; } + + /// <summary> + /// Adds the images. + /// </summary> + /// <param name="imageType">Type of the image.</param> + /// <param name="images">The images.</param> + /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> + bool AddImages(ImageType imageType, List<FileSystemMetadata> images); + + /// <summary> + /// Determines whether [is save local metadata enabled]. + /// </summary> + /// <returns><c>true</c> if [is save local metadata enabled]; otherwise, <c>false</c>.</returns> + bool IsSaveLocalMetadataEnabled(); + + /// <summary> + /// Gets a value indicating whether [supports local metadata]. + /// </summary> + /// <value><c>true</c> if [supports local metadata]; otherwise, <c>false</c>.</value> + bool SupportsLocalMetadata { get; } + + bool IsInMixedFolder { get; } + + /// <summary> + /// Gets a value indicating whether this instance is locked. + /// </summary> + /// <value><c>true</c> if this instance is locked; otherwise, <c>false</c>.</value> + bool IsLocked { get; } + + /// <summary> + /// Gets a value indicating whether [supports remote image downloading]. + /// </summary> + /// <value><c>true</c> if [supports remote image downloading]; otherwise, <c>false</c>.</value> + bool SupportsRemoteImageDownloading { get; } + + /// <summary> + /// Gets the internal metadata path. + /// </summary> + /// <returns>System.String.</returns> + string GetInternalMetadataPath(); + + /// <summary> + /// Gets a value indicating whether [always scan internal metadata path]. + /// </summary> + /// <value><c>true</c> if [always scan internal metadata path]; otherwise, <c>false</c>.</value> + bool AlwaysScanInternalMetadataPath { get; } + + /// <summary> + /// Determines whether [is internet metadata enabled]. + /// </summary> + /// <returns><c>true</c> if [is internet metadata enabled]; otherwise, <c>false</c>.</returns> + bool IsInternetMetadataEnabled(); + + /// <summary> + /// Removes the image. + /// </summary> + /// <param name="image">The image.</param> + void RemoveImage(ItemImageInfo image); + + void RemoveImages(List<ItemImageInfo> images); + + /// <summary> + /// Updates to repository. + /// </summary> + /// <param name="updateReason">The update reason.</param> + /// <param name="cancellationToken">The cancellation token.</param> + /// <returns>Task.</returns> + Task UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken); + + /// <summary> + /// Sets the image. + /// </summary> + /// <param name="image">The image.</param> + /// <param name="index">The index.</param> + void SetImage(ItemImageInfo image, int index); + + double? GetDefaultPrimaryImageAspectRatio(); + + int? ProductionYear { get; set; } + + string[] Tags { get; set; } + } + + public static class HasMetadataExtensions + { + /// <summary> + /// Gets the image path. + /// </summary> + /// <param name="item">The item.</param> + /// <param name="imageType">Type of the image.</param> + /// <returns>System.String.</returns> + public static string GetImagePath(this IHasMetadata item, ImageType imageType) + { + return item.GetImagePath(imageType, 0); + } + + public static bool HasImage(this IHasMetadata item, ImageType imageType) + { + return item.HasImage(imageType, 0); + } + + /// <summary> + /// Sets the image path. + /// </summary> + /// <param name="item">The item.</param> + /// <param name="imageType">Type of the image.</param> + /// <param name="file">The file.</param> + public static void SetImagePath(this IHasMetadata item, ImageType imageType, FileSystemMetadata file) + { + item.SetImagePath(imageType, 0, file); + } + + /// <summary> + /// Sets the image path. + /// </summary> + /// <param name="item">The item.</param> + /// <param name="imageType">Type of the image.</param> + /// <param name="file">The file.</param> + public static void SetImagePath(this IHasMetadata item, ImageType imageType, string file) + { + if (file.StartsWith("http", System.StringComparison.OrdinalIgnoreCase)) + { + item.SetImage(new ItemImageInfo + { + Path = file, + Type = imageType + }, 0); + } + else + { + item.SetImagePath(imageType, BaseItem.FileSystem.GetFileInfo(file)); + } + } } } diff --git a/MediaBrowser.Controller/Entities/IHasSpecialFeatures.cs b/MediaBrowser.Controller/Entities/IHasSpecialFeatures.cs index b3a0dc237..f4905b7dc 100644 --- a/MediaBrowser.Controller/Entities/IHasSpecialFeatures.cs +++ b/MediaBrowser.Controller/Entities/IHasSpecialFeatures.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; namespace MediaBrowser.Controller.Entities { @@ -9,6 +8,6 @@ namespace MediaBrowser.Controller.Entities /// Gets or sets the special feature ids. /// </summary> /// <value>The special feature ids.</value> - List<Guid> SpecialFeatureIds { get; set; } + Guid[] SpecialFeatureIds { get; set; } } } diff --git a/MediaBrowser.Controller/Entities/IHasTrailers.cs b/MediaBrowser.Controller/Entities/IHasTrailers.cs index e5cbdff72..8686c802a 100644 --- a/MediaBrowser.Controller/Entities/IHasTrailers.cs +++ b/MediaBrowser.Controller/Entities/IHasTrailers.cs @@ -11,14 +11,14 @@ namespace MediaBrowser.Controller.Entities /// Gets or sets the remote trailers. /// </summary> /// <value>The remote trailers.</value> - List<MediaUrl> RemoteTrailers { get; set; } + MediaUrl[] RemoteTrailers { get; set; } /// <summary> /// Gets or sets the local trailer ids. /// </summary> /// <value>The local trailer ids.</value> - List<Guid> LocalTrailerIds { get; set; } - List<Guid> RemoteTrailerIds { get; set; } + Guid[] LocalTrailerIds { get; set; } + Guid[] RemoteTrailerIds { get; set; } } public static class HasTrailerExtensions diff --git a/MediaBrowser.Controller/Entities/IHasUserData.cs b/MediaBrowser.Controller/Entities/IHasUserData.cs index 0029947ee..ab4f624e2 100644 --- a/MediaBrowser.Controller/Entities/IHasUserData.cs +++ b/MediaBrowser.Controller/Entities/IHasUserData.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Threading.Tasks; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Querying; @@ -8,17 +9,19 @@ namespace MediaBrowser.Controller.Entities /// <summary> /// Interface IHasUserData /// </summary> - public interface IHasUserData : IHasId + public interface IHasUserData { List<string> GetUserDataKeys(); /// <summary> /// Fills the user data dto values. /// </summary> - void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user, List<ItemFields> fields); + void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user, ItemFields[] fields); bool EnableRememberingTrackSelections { get; } bool SupportsPlayedStatus { get; } + + Guid Id { get; } } } diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index 4f21aaa56..03dc18b7a 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -16,10 +16,6 @@ namespace MediaBrowser.Controller.Entities public int? Limit { get; set; } - public string[] SortBy { get; set; } - - public SortOrder SortOrder { get; set; } - public User User { get; set; } public BaseItem SimilarTo { get; set; } @@ -42,7 +38,6 @@ namespace MediaBrowser.Controller.Entities public bool? IsSpecialSeason { get; set; } public bool? IsMissing { get; set; } public bool? IsUnaired { get; set; } - public bool? IsVirtualUnaired { get; set; } public bool? CollapseBoxSetItems { get; set; } public string NameStartsWithOrGreater { get; set; } @@ -149,7 +144,6 @@ namespace MediaBrowser.Controller.Entities public TrailerType[] TrailerTypes { get; set; } public SourceType[] SourceTypes { get; set; } - public DayOfWeek[] AirDays { get; set; } public SeriesStatus[] SeriesStatuses { get; set; } public string ExternalSeriesId { get; set; } public string ExternalId { get; set; } @@ -161,12 +155,13 @@ namespace MediaBrowser.Controller.Entities public string SeriesPresentationUniqueKey { get; set; } public bool GroupByPresentationUniqueKey { get; set; } + public bool GroupBySeriesPresentationUniqueKey { get; set; } public bool EnableTotalRecordCount { get; set; } public bool ForceDirect { get; set; } public Dictionary<string, string> ExcludeProviderIds { get; set; } public bool EnableGroupByMetadataKey { get; set; } - public List<Tuple<string, SortOrder>> OrderBy { get; set; } + public Tuple<string, SortOrder>[] OrderBy { get; set; } public DateTime? MinDateCreated { get; set; } public DateTime? MinDateLastSaved { get; set; } @@ -191,7 +186,6 @@ namespace MediaBrowser.Controller.Entities BlockUnratedItems = new UnratedItem[] { }; Tags = new string[] { }; OfficialRatings = new string[] { }; - SortBy = new string[] { }; MediaTypes = new string[] { }; IncludeItemTypes = new string[] { }; ExcludeItemTypes = new string[] { }; @@ -213,9 +207,8 @@ namespace MediaBrowser.Controller.Entities PresetViews = new string[] { }; TrailerTypes = new TrailerType[] { }; SourceTypes = new SourceType[] { }; - AirDays = new DayOfWeek[] { }; SeriesStatuses = new SeriesStatus[] { }; - OrderBy = new List<Tuple<string, SortOrder>>(); + OrderBy = new Tuple<string, SortOrder>[] { }; } public InternalItemsQuery(User user) diff --git a/MediaBrowser.Controller/Entities/InternalPeopleQuery.cs b/MediaBrowser.Controller/Entities/InternalPeopleQuery.cs index 05d23d986..9e0e9c208 100644 --- a/MediaBrowser.Controller/Entities/InternalPeopleQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalPeopleQuery.cs @@ -6,7 +6,7 @@ namespace MediaBrowser.Controller.Entities public class InternalPeopleQuery { public Guid ItemId { get; set; } - public List<string> PersonTypes { get; set; } + public string[] PersonTypes { get; set; } public List<string> ExcludePersonTypes { get; set; } public int? MaxListOrder { get; set; } public Guid AppearsInItemId { get; set; } @@ -14,7 +14,7 @@ namespace MediaBrowser.Controller.Entities public InternalPeopleQuery() { - PersonTypes = new List<string>(); + PersonTypes = new string[] {}; ExcludePersonTypes = new List<string>(); } } diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index 071ed405f..900e8a664 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -1,5 +1,4 @@ -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Providers; +using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; @@ -8,7 +7,6 @@ using System; using System.Collections.Generic; using System.Linq; using MediaBrowser.Model.Serialization; -using MediaBrowser.Controller.Entities.Audio; namespace MediaBrowser.Controller.Entities.Movies { @@ -21,9 +19,9 @@ namespace MediaBrowser.Controller.Entities.Movies public BoxSet() { - RemoteTrailers = new List<MediaUrl>(); - LocalTrailerIds = new List<Guid>(); - RemoteTrailerIds = new List<Guid>(); + RemoteTrailers = EmptyMediaUrlArray; + LocalTrailerIds = EmptyGuidArray; + RemoteTrailerIds = EmptyGuidArray; DisplayOrder = ItemSortBy.PremiereDate; Shares = new List<Share>(); @@ -47,14 +45,14 @@ namespace MediaBrowser.Controller.Entities.Movies } } - public List<Guid> LocalTrailerIds { get; set; } - public List<Guid> RemoteTrailerIds { get; set; } + public Guid[] LocalTrailerIds { get; set; } + public Guid[] RemoteTrailerIds { get; set; } /// <summary> /// Gets or sets the remote trailers. /// </summary> /// <value>The remote trailers.</value> - public List<MediaUrl> RemoteTrailers { get; set; } + public MediaUrl[] RemoteTrailers { get; set; } /// <summary> /// Gets or sets the display order. @@ -82,20 +80,11 @@ namespace MediaBrowser.Controller.Entities.Movies protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService) { - if (IsLegacyBoxSet) - { - return base.GetNonCachedChildren(directoryService); - } return new List<BaseItem>(); } protected override List<BaseItem> LoadChildren() { - if (IsLegacyBoxSet) - { - return base.LoadChildren(); - } - // Save a trip to the database return new List<BaseItem>(); } @@ -109,34 +98,6 @@ namespace MediaBrowser.Controller.Entities.Movies } } - [IgnoreDataMember] - protected override bool SupportsShortcutChildren - { - get - { - if (IsLegacyBoxSet) - { - return true; - } - - return false; - } - } - - [IgnoreDataMember] - private bool IsLegacyBoxSet - { - get - { - if (string.IsNullOrWhiteSpace(Path)) - { - return false; - } - - return !FileSystem.ContainsSubPath(ConfigurationManager.ApplicationPaths.DataPath, Path); - } - } - public override bool IsAuthorizedToDelete(User user) { return true; @@ -148,17 +109,6 @@ namespace MediaBrowser.Controller.Entities.Movies } /// <summary> - /// Gets the trailer ids. - /// </summary> - /// <returns>List<Guid>.</returns> - public List<Guid> GetTrailerIds() - { - var list = LocalTrailerIds.ToList(); - list.AddRange(RemoteTrailerIds); - return list; - } - - /// <summary> /// Updates the official rating based on content and returns true or false indicating if it changed. /// </summary> /// <returns></returns> @@ -181,24 +131,24 @@ namespace MediaBrowser.Controller.Entities.Movies StringComparison.OrdinalIgnoreCase); } - public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren) + public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren) { var children = base.GetChildren(user, includeLinkedChildren); if (string.Equals(DisplayOrder, ItemSortBy.SortName, StringComparison.OrdinalIgnoreCase)) { // Sort by name - return LibraryManager.Sort(children, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending); + return LibraryManager.Sort(children, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).ToList(); } if (string.Equals(DisplayOrder, ItemSortBy.PremiereDate, StringComparison.OrdinalIgnoreCase)) { // Sort by release date - return LibraryManager.Sort(children, user, new[] { ItemSortBy.ProductionYear, ItemSortBy.PremiereDate, ItemSortBy.SortName }, SortOrder.Ascending); + return LibraryManager.Sort(children, user, new[] { ItemSortBy.ProductionYear, ItemSortBy.PremiereDate, ItemSortBy.SortName }, SortOrder.Ascending).ToList(); } // Default sorting - return LibraryManager.Sort(children, user, new[] { ItemSortBy.ProductionYear, ItemSortBy.PremiereDate, ItemSortBy.SortName }, SortOrder.Ascending); + return LibraryManager.Sort(children, user, new[] { ItemSortBy.ProductionYear, ItemSortBy.PremiereDate, ItemSortBy.SortName }, SortOrder.Ascending).ToList(); } public BoxSetInfo GetLookupInfo() @@ -218,7 +168,7 @@ namespace MediaBrowser.Controller.Entities.Movies if (base.IsVisible(user)) { - return base.GetChildren(user, true).Any(); + return base.GetChildren(user, true).Count > 0; } return false; diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index 8a5b726e2..3a41709fe 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -19,20 +19,20 @@ namespace MediaBrowser.Controller.Entities.Movies /// </summary> public class Movie : Video, IHasSpecialFeatures, IHasTrailers, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping { - public List<Guid> SpecialFeatureIds { get; set; } + public Guid[] SpecialFeatureIds { get; set; } public Movie() { - SpecialFeatureIds = new List<Guid>(); - RemoteTrailers = new List<MediaUrl>(); - LocalTrailerIds = new List<Guid>(); - RemoteTrailerIds = new List<Guid>(); + SpecialFeatureIds = EmptyGuidArray; + RemoteTrailers = EmptyMediaUrlArray; + LocalTrailerIds = EmptyGuidArray; + RemoteTrailerIds = EmptyGuidArray; } - public List<Guid> LocalTrailerIds { get; set; } - public List<Guid> RemoteTrailerIds { get; set; } + public Guid[] LocalTrailerIds { get; set; } + public Guid[] RemoteTrailerIds { get; set; } - public List<MediaUrl> RemoteTrailers { get; set; } + public MediaUrl[] RemoteTrailers { get; set; } /// <summary> /// Gets or sets the name of the TMDB collection. @@ -55,22 +55,13 @@ namespace MediaBrowser.Controller.Entities.Movies return value; } - [IgnoreDataMember] - protected override bool SupportsIsInMixedFolderDetection - { - get - { - return false; - } - } - protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) { var hasChanges = await base.RefreshedOwnedItems(options, fileSystemChildren, cancellationToken).ConfigureAwait(false); // Must have a parent to have special features // In other words, it must be part of the Parent/Child tree - if (LocationType == LocationType.FileSystem && GetParent() != null && !DetectIsInMixedFolder()) + if (LocationType == LocationType.FileSystem && GetParent() != null && !IsInMixedFolder) { var specialFeaturesChanged = await RefreshSpecialFeatures(options, fileSystemChildren, cancellationToken).ConfigureAwait(false); @@ -86,7 +77,7 @@ namespace MediaBrowser.Controller.Entities.Movies private async Task<bool> RefreshSpecialFeatures(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) { var newItems = LibraryManager.FindExtras(this, fileSystemChildren, options.DirectoryService).ToList(); - var newItemIds = newItems.Select(i => i.Id).ToList(); + var newItemIds = newItems.Select(i => i.Id).ToArray(); var itemsChanged = !SpecialFeatureIds.SequenceEqual(newItemIds); @@ -108,7 +99,7 @@ namespace MediaBrowser.Controller.Entities.Movies { var info = GetItemLookupInfo<MovieInfo>(); - if (!DetectIsInMixedFolder()) + if (!IsInMixedFolder) { var name = System.IO.Path.GetFileName(ContainingFolderPath); @@ -145,7 +136,7 @@ namespace MediaBrowser.Controller.Entities.Movies else { // Try to get the year from the folder name - if (!DetectIsInMixedFolder()) + if (!IsInMixedFolder) { info = LibraryManager.ParseName(System.IO.Path.GetFileName(ContainingFolderPath)); diff --git a/MediaBrowser.Controller/Entities/MusicVideo.cs b/MediaBrowser.Controller/Entities/MusicVideo.cs index 7344cb8e4..b7470d679 100644 --- a/MediaBrowser.Controller/Entities/MusicVideo.cs +++ b/MediaBrowser.Controller/Entities/MusicVideo.cs @@ -8,15 +8,16 @@ namespace MediaBrowser.Controller.Entities { public class MusicVideo : Video, IHasArtist, IHasMusicGenres, IHasLookupInfo<MusicVideoInfo> { - public List<string> Artists { get; set; } + [IgnoreDataMember] + public string[] Artists { get; set; } public MusicVideo() { - Artists = new List<string>(); + Artists = EmptyStringArray; } [IgnoreDataMember] - public List<string> AllArtists + public string[] AllArtists { get { @@ -24,15 +25,6 @@ namespace MediaBrowser.Controller.Entities } } - [IgnoreDataMember] - protected override bool SupportsIsInMixedFolderDetection - { - get - { - return false; - } - } - public override UnratedItem GetBlockUnratedType() { return UnratedItem.Music; @@ -61,7 +53,7 @@ namespace MediaBrowser.Controller.Entities else { // Try to get the year from the folder name - if (!DetectIsInMixedFolder()) + if (!IsInMixedFolder) { info = LibraryManager.ParseName(System.IO.Path.GetFileName(ContainingFolderPath)); diff --git a/MediaBrowser.Controller/Entities/PeopleHelper.cs b/MediaBrowser.Controller/Entities/PeopleHelper.cs index 40a93d9e6..412eb9499 100644 --- a/MediaBrowser.Controller/Entities/PeopleHelper.cs +++ b/MediaBrowser.Controller/Entities/PeopleHelper.cs @@ -105,7 +105,15 @@ namespace MediaBrowser.Controller.Entities { throw new ArgumentNullException("name"); } - return people.Any(i => string.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase)); + + foreach (var i in people) + { + if (string.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + return false; } } } diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs index 20d9c7999..b3a91f944 100644 --- a/MediaBrowser.Controller/Entities/Person.cs +++ b/MediaBrowser.Controller/Entities/Person.cs @@ -1,7 +1,6 @@ using MediaBrowser.Controller.Providers; using System; using System.Collections.Generic; -using System.Linq; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Extensions; using MediaBrowser.Model.Entities; diff --git a/MediaBrowser.Controller/Entities/Photo.cs b/MediaBrowser.Controller/Entities/Photo.cs index e95ceee52..8e9eac50c 100644 --- a/MediaBrowser.Controller/Entities/Photo.cs +++ b/MediaBrowser.Controller/Entities/Photo.cs @@ -1,5 +1,4 @@ using MediaBrowser.Model.Drawing; -using System.Linq; using MediaBrowser.Model.Serialization; namespace MediaBrowser.Controller.Entities @@ -39,7 +38,16 @@ namespace MediaBrowser.Controller.Entities { get { - return GetParents().OfType<PhotoAlbum>().FirstOrDefault(); + var parents = GetParents(); + foreach (var parent in parents) + { + var photoAlbum = parent as PhotoAlbum; + if (photoAlbum != null) + { + return photoAlbum; + } + } + return null; } } diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs index 8cb65c60a..a6a72d994 100644 --- a/MediaBrowser.Controller/Entities/Studio.cs +++ b/MediaBrowser.Controller/Entities/Studio.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using MediaBrowser.Model.Serialization; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Extensions; diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index 45b4de1b3..c30e0ef8e 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -17,14 +17,14 @@ namespace MediaBrowser.Controller.Entities.TV {
public Episode()
{
- RemoteTrailers = new List<MediaUrl>();
- LocalTrailerIds = new List<Guid>();
- RemoteTrailerIds = new List<Guid>();
+ RemoteTrailers = EmptyMediaUrlArray;
+ LocalTrailerIds = EmptyGuidArray;
+ RemoteTrailerIds = EmptyGuidArray;
}
- public List<Guid> LocalTrailerIds { get; set; }
- public List<Guid> RemoteTrailerIds { get; set; }
- public List<MediaUrl> RemoteTrailers { get; set; }
+ public Guid[] LocalTrailerIds { get; set; }
+ public Guid[] RemoteTrailerIds { get; set; }
+ public MediaUrl[] RemoteTrailers { get; set; }
/// <summary>
/// Gets the season in which it aired.
@@ -282,17 +282,11 @@ namespace MediaBrowser.Controller.Entities.TV {
get
{
- return LocationType == LocationType.Virtual && !IsUnaired;
+ return LocationType == LocationType.Virtual;
}
}
[IgnoreDataMember]
- public bool IsVirtualUnaired
- {
- get { return LocationType == LocationType.Virtual && IsUnaired; }
- }
-
- [IgnoreDataMember]
public Guid? SeasonId { get; set; }
[IgnoreDataMember]
public Guid? SeriesId { get; set; }
@@ -346,7 +340,6 @@ namespace MediaBrowser.Controller.Entities.TV id.IsMissingEpisode = IsMissingEpisode;
id.IndexNumberEnd = IndexNumberEnd;
- id.IsVirtualUnaired = IsVirtualUnaired;
return id;
}
diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index b681fdcb1..bf6dc5678 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -81,7 +81,7 @@ namespace MediaBrowser.Controller.Entities.TV public override int GetChildCount(User user) { - var result = GetChildren(user, true).Count(); + var result = GetChildren(user, true).Count; return result; } @@ -160,27 +160,27 @@ namespace MediaBrowser.Controller.Entities.TV /// <summary> /// Gets the episodes. /// </summary> - public IEnumerable<Episode> GetEpisodes(User user, DtoOptions options) + public List<BaseItem> GetEpisodes(User user, DtoOptions options) { return GetEpisodes(Series, user, options); } - public IEnumerable<Episode> GetEpisodes(Series series, User user, DtoOptions options) + public List<BaseItem> GetEpisodes(Series series, User user, DtoOptions options) { return GetEpisodes(series, user, null, options); } - public IEnumerable<Episode> GetEpisodes(Series series, User user, IEnumerable<Episode> allSeriesEpisodes, DtoOptions options) + public List<BaseItem> GetEpisodes(Series series, User user, IEnumerable<Episode> allSeriesEpisodes, DtoOptions options) { return series.GetSeasonEpisodes(this, user, allSeriesEpisodes, options); } - public IEnumerable<Episode> GetEpisodes() + public List<BaseItem> GetEpisodes() { return Series.GetSeasonEpisodes(this, null, null, new DtoOptions(true)); } - public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren) + public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren) { return GetEpisodes(user, new DtoOptions(true)); } diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 8b73b80b0..60d2624fa 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -22,13 +22,15 @@ namespace MediaBrowser.Controller.Entities.TV { public Series() { - AirDays = new List<DayOfWeek>(); - - RemoteTrailers = new List<MediaUrl>(); - LocalTrailerIds = new List<Guid>(); - RemoteTrailerIds = new List<Guid>(); + RemoteTrailers = EmptyMediaUrlArray; + LocalTrailerIds = EmptyGuidArray; + RemoteTrailerIds = EmptyGuidArray; + AirDays = new DayOfWeek[] { }; } + public DayOfWeek[] AirDays { get; set; } + public string AirTime { get; set; } + [IgnoreDataMember] public override bool SupportsAddingToPlaylist { @@ -62,10 +64,10 @@ namespace MediaBrowser.Controller.Entities.TV } } - public List<Guid> LocalTrailerIds { get; set; } - public List<Guid> RemoteTrailerIds { get; set; } + public Guid[] LocalTrailerIds { get; set; } + public Guid[] RemoteTrailerIds { get; set; } - public List<MediaUrl> RemoteTrailers { get; set; } + public MediaUrl[] RemoteTrailers { get; set; } /// <summary> /// airdate, dvd or absolute @@ -77,16 +79,6 @@ namespace MediaBrowser.Controller.Entities.TV /// </summary> /// <value>The status.</value> public SeriesStatus? Status { get; set; } - /// <summary> - /// Gets or sets the air days. - /// </summary> - /// <value>The air days.</value> - public List<DayOfWeek> AirDays { get; set; } - /// <summary> - /// Gets or sets the air time. - /// </summary> - /// <value>The air time.</value> - public string AirTime { get; set; } /// <summary> /// Gets or sets the date last episode added. @@ -160,12 +152,8 @@ namespace MediaBrowser.Controller.Entities.TV IncludeItemTypes = new[] { typeof(Season).Name }, IsVirtualItem = false, Limit = 0, - DtoOptions = new Dto.DtoOptions + DtoOptions = new Dto.DtoOptions(false) { - Fields = new List<ItemFields> - { - - }, EnableImages = false } }); @@ -181,19 +169,15 @@ namespace MediaBrowser.Controller.Entities.TV { AncestorWithPresentationUniqueKey = null, SeriesPresentationUniqueKey = seriesKey, - DtoOptions = new Dto.DtoOptions + DtoOptions = new Dto.DtoOptions(false) { - Fields = new List<ItemFields> - { - - }, EnableImages = false } }; if (query.IncludeItemTypes.Length == 0) { - query.IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name }; + query.IncludeItemTypes = new[] { typeof(Episode).Name }; } query.IsVirtualItem = false; query.Limit = 0; @@ -225,32 +209,29 @@ namespace MediaBrowser.Controller.Entities.TV return list; } - /// <summary> - /// Gets the trailer ids. - /// </summary> - /// <returns>List<Guid>.</returns> - public List<Guid> GetTrailerIds() - { - var list = LocalTrailerIds.ToList(); - list.AddRange(RemoteTrailerIds); - return list; - } - [IgnoreDataMember] public bool ContainsEpisodesWithoutSeasonFolders { get { - return Children.OfType<Video>().Any(); + var children = Children; + foreach (var child in children) + { + if (child is Video) + { + return true; + } + } + return false; } } - public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren) + public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren) { return GetSeasons(user, new DtoOptions(true)); } - public IEnumerable<Season> GetSeasons(User user, DtoOptions options) + public List<BaseItem> GetSeasons(User user, DtoOptions options) { var query = new InternalItemsQuery(user) { @@ -259,7 +240,7 @@ namespace MediaBrowser.Controller.Entities.TV SetSeasonQueryOptions(query, user); - return LibraryManager.GetItemList(query).Cast<Season>(); + return LibraryManager.GetItemList(query); } private void SetSeasonQueryOptions(InternalItemsQuery query, User user) @@ -271,20 +252,12 @@ namespace MediaBrowser.Controller.Entities.TV query.AncestorWithPresentationUniqueKey = null; query.SeriesPresentationUniqueKey = seriesKey; query.IncludeItemTypes = new[] { typeof(Season).Name }; - query.SortBy = new[] {ItemSortBy.SortName}; + query.OrderBy = new[] { ItemSortBy.SortName }.Select(i => new Tuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(); - if (!config.DisplayMissingEpisodes && !config.DisplayUnairedEpisodes) - { - query.IsVirtualItem = false; - } - else if (!config.DisplayMissingEpisodes) + if (!config.DisplayMissingEpisodes) { query.IsMissing = false; } - else if (!config.DisplayUnairedEpisodes) - { - query.IsVirtualUnaired = false; - } } protected override QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query) @@ -302,9 +275,9 @@ namespace MediaBrowser.Controller.Entities.TV query.AncestorWithPresentationUniqueKey = null; query.SeriesPresentationUniqueKey = seriesKey; - if (query.SortBy.Length == 0) + if (query.OrderBy.Length == 0) { - query.SortBy = new[] { ItemSortBy.SortName }; + query.OrderBy = new[] { ItemSortBy.SortName }.Select(i => new Tuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(); } if (query.IncludeItemTypes.Length == 0) { @@ -319,7 +292,7 @@ namespace MediaBrowser.Controller.Entities.TV return LibraryManager.GetItemsResult(query); } - public IEnumerable<Episode> GetEpisodes(User user, DtoOptions options) + public IEnumerable<BaseItem> GetEpisodes(User user, DtoOptions options) { var seriesKey = GetUniqueSeriesKey(this); @@ -328,31 +301,22 @@ namespace MediaBrowser.Controller.Entities.TV AncestorWithPresentationUniqueKey = null, SeriesPresentationUniqueKey = seriesKey, IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name }, - SortBy = new[] { ItemSortBy.SortName }, + OrderBy = new[] { ItemSortBy.SortName }.Select(i => new Tuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(), DtoOptions = options }; var config = user.Configuration; - if (!config.DisplayMissingEpisodes && !config.DisplayUnairedEpisodes) - { - query.IsVirtualItem = false; - } - else if (!config.DisplayMissingEpisodes) + if (!config.DisplayMissingEpisodes) { query.IsMissing = false; } - else if (!config.DisplayUnairedEpisodes) - { - query.IsVirtualUnaired = false; - } - var allItems = LibraryManager.GetItemList(query).ToList(); + var allItems = LibraryManager.GetItemList(query); var allSeriesEpisodes = allItems.OfType<Episode>().ToList(); var allEpisodes = allItems.OfType<Season>() .SelectMany(i => i.GetEpisodes(this, user, allSeriesEpisodes, options)) - .Reverse() - .ToList(); + .Reverse(); // Specials could appear twice based on above - once in season 0, once in the aired season // This depends on settings for that series @@ -365,20 +329,22 @@ namespace MediaBrowser.Controller.Entities.TV { // Refresh bottom up, children first, then the boxset // By then hopefully the movies within will have Tmdb collection values - var items = GetRecursiveChildren().ToList(); + var items = GetRecursiveChildren(); - var seasons = items.OfType<Season>().ToList(); - var otherItems = items.Except(seasons).ToList(); - - var totalItems = seasons.Count + otherItems.Count; + var totalItems = items.Count; var numComplete = 0; // Refresh current item await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); // Refresh seasons - foreach (var item in seasons) + foreach (var item in items) { + if (!(item is Season)) + { + continue; + } + cancellationToken.ThrowIfCancellationRequested(); await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); @@ -390,8 +356,13 @@ namespace MediaBrowser.Controller.Entities.TV } // Refresh episodes and other children - foreach (var item in otherItems) + foreach (var item in items) { + if ((item is Season)) + { + continue; + } + cancellationToken.ThrowIfCancellationRequested(); var skipItem = false; @@ -425,7 +396,7 @@ namespace MediaBrowser.Controller.Entities.TV await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false); } - public IEnumerable<Episode> GetSeasonEpisodes(Season parentSeason, User user, DtoOptions options) + public List<BaseItem> GetSeasonEpisodes(Season parentSeason, User user, DtoOptions options) { var queryFromSeries = ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons; @@ -439,32 +410,24 @@ namespace MediaBrowser.Controller.Entities.TV AncestorWithPresentationUniqueKey = queryFromSeries ? null : seriesKey, SeriesPresentationUniqueKey = queryFromSeries ? seriesKey : null, IncludeItemTypes = new[] { typeof(Episode).Name }, - SortBy = new[] { ItemSortBy.SortName }, + OrderBy = new[] { ItemSortBy.SortName }.Select(i => new Tuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(), DtoOptions = options }; if (user != null) { var config = user.Configuration; - if (!config.DisplayMissingEpisodes && !config.DisplayUnairedEpisodes) - { - query.IsVirtualItem = false; - } - else if (!config.DisplayMissingEpisodes) + if (!config.DisplayMissingEpisodes) { query.IsMissing = false; } - else if (!config.DisplayUnairedEpisodes) - { - query.IsVirtualUnaired = false; - } } - var allItems = LibraryManager.GetItemList(query).OfType<Episode>(); + var allItems = LibraryManager.GetItemList(query); return GetSeasonEpisodes(parentSeason, user, allItems, options); } - public IEnumerable<Episode> GetSeasonEpisodes(Season parentSeason, User user, IEnumerable<Episode> allSeriesEpisodes, DtoOptions options) + public List<BaseItem> GetSeasonEpisodes(Season parentSeason, User user, IEnumerable<BaseItem> allSeriesEpisodes, DtoOptions options) { if (allSeriesEpisodes == null) { @@ -475,14 +438,13 @@ namespace MediaBrowser.Controller.Entities.TV var sortBy = (parentSeason.IndexNumber ?? -1) == 0 ? ItemSortBy.SortName : ItemSortBy.AiredEpisodeOrder; - return LibraryManager.Sort(episodes, user, new[] { sortBy }, SortOrder.Ascending) - .Cast<Episode>(); + return LibraryManager.Sort(episodes, user, new[] { sortBy }, SortOrder.Ascending).ToList(); } /// <summary> /// Filters the episodes by season. /// </summary> - public static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, Season parentSeason, bool includeSpecials) + public static IEnumerable<BaseItem> FilterEpisodesBySeason(IEnumerable<BaseItem> episodes, Season parentSeason, bool includeSpecials) { var seasonNumber = parentSeason.IndexNumber; var seasonPresentationKey = GetUniqueSeriesKey(parentSeason); @@ -491,7 +453,9 @@ namespace MediaBrowser.Controller.Entities.TV return episodes.Where(episode => { - var currentSeasonNumber = supportSpecialsInSeason ? episode.AiredSeasonNumber : episode.ParentIndexNumber; + var episodeItem = (Episode)episode; + + var currentSeasonNumber = supportSpecialsInSeason ? episodeItem.AiredSeasonNumber : episode.ParentIndexNumber; if (currentSeasonNumber.HasValue && seasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber.Value) { return true; @@ -502,7 +466,7 @@ namespace MediaBrowser.Controller.Entities.TV return true; } - var season = episode.Season; + var season = episodeItem.Season; return season != null && string.Equals(GetUniqueSeriesKey(season), seasonPresentationKey, StringComparison.OrdinalIgnoreCase); }); } diff --git a/MediaBrowser.Controller/Entities/TagExtensions.cs b/MediaBrowser.Controller/Entities/TagExtensions.cs index 0e1df72cd..e5d8f35d9 100644 --- a/MediaBrowser.Controller/Entities/TagExtensions.cs +++ b/MediaBrowser.Controller/Entities/TagExtensions.cs @@ -1,5 +1,7 @@ using System; +using System.Collections.Generic; using System.Linq; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Controller.Entities { @@ -12,9 +14,21 @@ namespace MediaBrowser.Controller.Entities throw new ArgumentNullException("name"); } - if (!item.Tags.Contains(name, StringComparer.OrdinalIgnoreCase)) + var current = item.Tags; + + if (!current.Contains(name, StringComparer.OrdinalIgnoreCase)) { - item.Tags.Add(name); + if (current.Length == 0) + { + item.Tags = new[] { name }; + } + else + { + var list = current.ToArray(current.Length + 1); + list[list.Length - 1] = name; + + item.Tags = list; + } } } } diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs index 99acce164..c5144aadf 100644 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ b/MediaBrowser.Controller/Entities/Trailer.cs @@ -47,7 +47,7 @@ namespace MediaBrowser.Controller.Entities info.IsLocalTrailer = TrailerTypes.Contains(TrailerType.LocalTrailer); - if (!DetectIsInMixedFolder() && LocationType == LocationType.FileSystem) + if (!IsInMixedFolder && LocationType == LocationType.FileSystem) { info.Name = System.IO.Path.GetFileName(ContainingFolderPath); } @@ -73,7 +73,7 @@ namespace MediaBrowser.Controller.Entities else { // Try to get the year from the folder name - if (!DetectIsInMixedFolder()) + if (!IsInMixedFolder) { info = LibraryManager.ParseName(System.IO.Path.GetFileName(ContainingFolderPath)); diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs index d5d229bb3..3c89037cc 100644 --- a/MediaBrowser.Controller/Entities/User.cs +++ b/MediaBrowser.Controller/Entities/User.cs @@ -5,7 +5,6 @@ using MediaBrowser.Model.Connect; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Users; using System; -using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -166,7 +165,7 @@ namespace MediaBrowser.Controller.Entities } } } - + return _policy; } set { _policy = value; } @@ -195,24 +194,24 @@ namespace MediaBrowser.Controller.Entities var oldConfigurationDirectory = ConfigurationDirectoryPath; // Exceptions will be thrown if these paths already exist - if (FileSystem.DirectoryExists(newConfigDirectory)) + if (FileSystem.DirectoryExists(newConfigDirectory)) { FileSystem.DeleteDirectory(newConfigDirectory, true); } - if (FileSystem.DirectoryExists(oldConfigurationDirectory)) + if (FileSystem.DirectoryExists(oldConfigurationDirectory)) { - FileSystem.MoveDirectory(oldConfigurationDirectory, newConfigDirectory); + FileSystem.MoveDirectory(oldConfigurationDirectory, newConfigDirectory); } else { - FileSystem.CreateDirectory(newConfigDirectory); + FileSystem.CreateDirectory(newConfigDirectory); } } Name = newName; - return RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(Logger, FileSystem)) + return RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(Logger, FileSystem)) { ReplaceAllMetadata = true, ImageRefreshMode = ImageRefreshMode.FullRefresh, @@ -224,7 +223,8 @@ namespace MediaBrowser.Controller.Entities public override Task UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken) { - return UserManager.UpdateUser(this); + UserManager.UpdateUser(this); + return Task.FromResult(true); } /// <summary> @@ -279,7 +279,14 @@ namespace MediaBrowser.Controller.Entities return true; } - return schedules.Any(i => IsParentalScheduleAllowed(i, date)); + foreach (var i in schedules) + { + if (IsParentalScheduleAllowed(i, date)) + { + return true; + } + } + return false; } private bool IsParentalScheduleAllowed(AccessSchedule schedule, DateTime date) @@ -304,7 +311,14 @@ namespace MediaBrowser.Controller.Entities public bool IsFolderGrouped(Guid id) { - return Configuration.GroupedFolders.Select(i => new Guid(i)).Contains(id); + foreach (var i in Configuration.GroupedFolders) + { + if (new Guid(i) == id) + { + return true; + } + } + return false; } [IgnoreDataMember] diff --git a/MediaBrowser.Controller/Entities/UserRootFolder.cs b/MediaBrowser.Controller/Entities/UserRootFolder.cs index d35156345..2ed3bf20f 100644 --- a/MediaBrowser.Controller/Entities/UserRootFolder.cs +++ b/MediaBrowser.Controller/Entities/UserRootFolder.cs @@ -24,7 +24,7 @@ namespace MediaBrowser.Controller.Entities { if (_childrenIds == null) { - var list = base.LoadChildren().ToList(); + var list = base.LoadChildren(); _childrenIds = list.Select(i => i.Id).ToList(); return list; } @@ -81,7 +81,7 @@ namespace MediaBrowser.Controller.Entities public override int GetChildCount(User user) { - return GetChildren(user, true).Count(); + return GetChildren(user, true).Count; } [IgnoreDataMember] diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index 0d2d69c94..66174034d 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -4,9 +4,9 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; using System; using System.Collections.Generic; +using System.Linq; using MediaBrowser.Model.Serialization; using System.Threading.Tasks; -using System.Linq; using MediaBrowser.Controller.Dto; namespace MediaBrowser.Controller.Entities @@ -60,7 +60,7 @@ namespace MediaBrowser.Controller.Entities public override int GetChildCount(User user) { - return GetChildren(user, true).Count(); + return GetChildren(user, true).Count; } protected override QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query) @@ -80,9 +80,9 @@ namespace MediaBrowser.Controller.Entities .GetUserItems(parent, this, ViewType, query).Result; } - public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren) + public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren) { - var result = GetItems(new InternalItemsQuery + var result = GetItemList(new InternalItemsQuery { User = user, EnableTotalRecordCount = false, @@ -90,7 +90,7 @@ namespace MediaBrowser.Controller.Entities }); - return result.Items; + return result.ToList(); } public override bool CanDelete() @@ -105,7 +105,7 @@ namespace MediaBrowser.Controller.Entities public override IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query) { - var result = GetItems(new InternalItemsQuery + var result = GetItemList(new InternalItemsQuery { User = user, Recursive = true, @@ -117,7 +117,7 @@ namespace MediaBrowser.Controller.Entities }); - return result.Items.Where(i => UserViewBuilder.FilterItem(i, query)); + return result.Where(i => UserViewBuilder.FilterItem(i, query)); } protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user) diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index 91e24caeb..3ab82a103 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -397,7 +397,7 @@ namespace MediaBrowser.Controller.Entities }, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null); - query.SortBy = new string[] { }; + query.OrderBy = new Tuple<string, SortOrder>[] { }; return PostFilterAndSort(items, parent, null, query, false, true); } @@ -507,8 +507,7 @@ namespace MediaBrowser.Controller.Entities private QueryResult<BaseItem> GetMovieLatest(Folder parent, User user, InternalItemsQuery query) { - query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }; - query.SortOrder = SortOrder.Descending; + query.OrderBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }.Select(i => new Tuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(); query.Recursive = true; query.Parent = parent; @@ -521,8 +520,7 @@ namespace MediaBrowser.Controller.Entities private QueryResult<BaseItem> GetMovieResume(Folder parent, User user, InternalItemsQuery query) { - query.SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName }; - query.SortOrder = SortOrder.Descending; + query.OrderBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName }.Select(i => new Tuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(); query.IsResumable = true; query.Recursive = true; query.Parent = parent; @@ -533,7 +531,7 @@ namespace MediaBrowser.Controller.Entities return ConvertToResult(_libraryManager.GetItemList(query)); } - private QueryResult<BaseItem> ConvertToResult(IEnumerable<BaseItem> items) + private QueryResult<BaseItem> ConvertToResult(List<BaseItem> items) { var arr = items.ToArray(); return new QueryResult<BaseItem> @@ -633,8 +631,7 @@ namespace MediaBrowser.Controller.Entities private QueryResult<BaseItem> GetTvLatest(Folder parent, User user, InternalItemsQuery query) { - query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }; - query.SortOrder = SortOrder.Descending; + query.OrderBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }.Select(i => new Tuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(); query.Recursive = true; query.Parent = parent; @@ -663,8 +660,7 @@ namespace MediaBrowser.Controller.Entities private QueryResult<BaseItem> GetTvResume(Folder parent, User user, InternalItemsQuery query) { - query.SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName }; - query.SortOrder = SortOrder.Descending; + query.OrderBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName }.Select(i => new Tuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(); query.IsResumable = true; query.Recursive = true; query.Parent = parent; @@ -779,7 +775,6 @@ namespace MediaBrowser.Controller.Entities items = FilterVirtualEpisodes(items, query.IsMissing, - query.IsVirtualUnaired, query.IsUnaired); if (collapseBoxSetItems && user != null) @@ -790,7 +785,7 @@ namespace MediaBrowser.Controller.Entities // This must be the last filter if (!string.IsNullOrEmpty(query.AdjacentTo)) { - items = FilterForAdjacency(items, query.AdjacentTo); + items = FilterForAdjacency(items.ToList(), query.AdjacentTo); } return SortAndPage(items, totalRecordLimit, query, libraryManager, enableSorting); @@ -1065,7 +1060,6 @@ namespace MediaBrowser.Controller.Entities private static IEnumerable<BaseItem> FilterVirtualEpisodes( IEnumerable<BaseItem> items, bool? isMissing, - bool? isVirtualUnaired, bool? isUnaired) { if (isMissing.HasValue) @@ -1096,20 +1090,6 @@ namespace MediaBrowser.Controller.Entities }); } - if (isVirtualUnaired.HasValue) - { - var val = isVirtualUnaired.Value; - items = items.Where(i => - { - var e = i as Episode; - if (e != null) - { - return e.IsVirtualUnaired == val; - } - return true; - }); - } - return items; } @@ -1120,9 +1100,9 @@ namespace MediaBrowser.Controller.Entities { items = items.DistinctBy(i => i.GetPresentationUniqueKey(), StringComparer.OrdinalIgnoreCase); - if (query.SortBy.Length > 0) + if (query.OrderBy.Length > 0) { - items = libraryManager.Sort(items, query.User, query.SortBy, query.SortOrder); + items = libraryManager.Sort(items, query.User, query.OrderBy); } var itemsArray = totalRecordLimit.HasValue ? items.Take(totalRecordLimit.Value).ToArray() : items.ToArray(); @@ -1387,8 +1367,8 @@ namespace MediaBrowser.Controller.Entities if (movie != null) { var ok = filterValue - ? movie.SpecialFeatureIds.Count > 0 - : movie.SpecialFeatureIds.Count == 0; + ? movie.SpecialFeatureIds.Length > 0 + : movie.SpecialFeatureIds.Length == 0; if (!ok) { @@ -1463,7 +1443,7 @@ namespace MediaBrowser.Controller.Entities { var filterValue = query.HasThemeSong.Value; - var themeCount = item.ThemeSongIds.Count; + var themeCount = item.ThemeSongIds.Length; var ok = filterValue ? themeCount > 0 : themeCount == 0; if (!ok) @@ -1476,7 +1456,7 @@ namespace MediaBrowser.Controller.Entities { var filterValue = query.HasThemeVideo.Value; - var themeCount = item.ThemeVideoIds.Count; + var themeCount = item.ThemeVideoIds.Length; var ok = filterValue ? themeCount > 0 : themeCount == 0; if (!ok) @@ -1674,15 +1654,6 @@ namespace MediaBrowser.Controller.Entities } } - if (query.AirDays.Length > 0) - { - var ok = new[] { item }.OfType<Series>().Any(p => p.AirDays != null && query.AirDays.Any(d => p.AirDays.Contains(d))); - if (!ok) - { - return false; - } - } - if (query.SeriesStatuses.Length > 0) { var ok = new[] { item }.OfType<Series>().Any(p => p.Status.HasValue && query.SeriesStatuses.Contains(p.Status.Value)); @@ -1788,10 +1759,8 @@ namespace MediaBrowser.Controller.Entities return _userViewManager.GetUserSubView(parent.Id.ToString("N"), type, sortName, CancellationToken.None); } - public static IEnumerable<BaseItem> FilterForAdjacency(IEnumerable<BaseItem> items, string adjacentToId) + public static IEnumerable<BaseItem> FilterForAdjacency(List<BaseItem> list, string adjacentToId) { - var list = items.ToList(); - var adjacentToIdGuid = new Guid(adjacentToId); var adjacentToItem = list.FirstOrDefault(i => i.Id == adjacentToIdGuid); diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index c5d9b9203..ffb601dc4 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -16,6 +16,7 @@ using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.IO; using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Controller.Entities { @@ -30,9 +31,9 @@ namespace MediaBrowser.Controller.Entities [IgnoreDataMember] public string PrimaryVersionId { get; set; } - public List<string> AdditionalParts { get; set; } - public List<string> LocalAlternateVersions { get; set; } - public List<LinkedChild> LinkedAlternateVersions { get; set; } + public string[] AdditionalParts { get; set; } + public string[] LocalAlternateVersions { get; set; } + public LinkedChild[] LinkedAlternateVersions { get; set; } [IgnoreDataMember] public override bool SupportsPlayedStatus @@ -77,15 +78,6 @@ namespace MediaBrowser.Controller.Entities } } - [IgnoreDataMember] - protected override bool SupportsIsInMixedFolderDetection - { - get - { - return true; - } - } - public override string CreatePresentationUniqueKey() { if (!string.IsNullOrWhiteSpace(PrimaryVersionId)) @@ -121,7 +113,7 @@ namespace MediaBrowser.Controller.Entities /// Gets or sets the subtitle paths. /// </summary> /// <value>The subtitle paths.</value> - public List<string> SubtitleFiles { get; set; } + public string[] SubtitleFiles { get; set; } /// <summary> /// Gets or sets a value indicating whether this instance has subtitles. @@ -157,18 +149,23 @@ namespace MediaBrowser.Controller.Entities /// <value>The video3 D format.</value> public Video3DFormat? Video3DFormat { get; set; } - /// <summary> - /// If the video is a folder-rip, this will hold the file list for the largest playlist - /// </summary> - public List<string> PlayableStreamFileNames { get; set; } - - /// <summary> - /// Gets the playable stream files. - /// </summary> - /// <returns>List{System.String}.</returns> - public List<string> GetPlayableStreamFiles() + public string[] GetPlayableStreamFileNames() { - return GetPlayableStreamFiles(Path); + var videoType = VideoType; + + if (videoType == VideoType.Iso && IsoType == Model.Entities.IsoType.BluRay) + { + videoType = VideoType.BluRay; + } + else if (videoType == VideoType.Iso && IsoType == Model.Entities.IsoType.Dvd) + { + videoType = VideoType.Dvd; + } + else + { + return new string[] { }; + } + return MediaEncoder.GetPlayableStreamFileNames(Path, videoType); } /// <summary> @@ -179,17 +176,15 @@ namespace MediaBrowser.Controller.Entities public Video() { - PlayableStreamFileNames = new List<string>(); - AdditionalParts = new List<string>(); - LocalAlternateVersions = new List<string>(); - SubtitleFiles = new List<string>(); - LinkedAlternateVersions = new List<LinkedChild>(); + AdditionalParts = EmptyStringArray; + LocalAlternateVersions = EmptyStringArray; + SubtitleFiles = EmptyStringArray; + LinkedAlternateVersions = EmptyLinkedChildArray; } public override bool CanDownload() { - if (VideoType == VideoType.HdDvd || VideoType == VideoType.Dvd || - VideoType == VideoType.BluRay) + if (VideoType == VideoType.Dvd || VideoType == VideoType.BluRay) { return false; } @@ -218,20 +213,20 @@ namespace MediaBrowser.Controller.Entities return item.MediaSourceCount; } } - return LinkedAlternateVersions.Count + LocalAlternateVersions.Count + 1; + return LinkedAlternateVersions.Length + LocalAlternateVersions.Length + 1; } } [IgnoreDataMember] public bool IsStacked { - get { return AdditionalParts.Count > 0; } + get { return AdditionalParts.Length > 0; } } [IgnoreDataMember] public bool HasLocalAlternateVersions { - get { return LocalAlternateVersions.Count > 0; } + get { return LocalAlternateVersions.Length > 0; } } public IEnumerable<Guid> GetAdditionalPartIds() @@ -245,6 +240,41 @@ namespace MediaBrowser.Controller.Entities } [IgnoreDataMember] + public override SourceType SourceType + { + get + { + if (IsActiveRecording()) + { + return SourceType.LiveTV; + } + + return base.SourceType; + } + } + + protected bool IsActiveRecording() + { + return LiveTvManager.GetActiveRecordingInfo(Path) != null; + } + + public override bool CanDelete() + { + if (IsActiveRecording()) + { + return false; + } + + return base.CanDelete(); + } + + [IgnoreDataMember] + public bool IsCompleteMedia + { + get { return !IsActiveRecording(); } + } + + [IgnoreDataMember] protected virtual bool EnableDefaultVideoUserDataKeys { get @@ -339,8 +369,7 @@ namespace MediaBrowser.Controller.Entities if (!IsPlaceHolder) { - if (VideoType == VideoType.BluRay || VideoType == VideoType.Dvd || - VideoType == VideoType.HdDvd) + if (VideoType == VideoType.BluRay || VideoType == VideoType.Dvd) { return Path; } @@ -357,7 +386,7 @@ namespace MediaBrowser.Controller.Entities { if (LocationType == LocationType.FileSystem) { - if (VideoType == VideoType.BluRay || VideoType == VideoType.Dvd || VideoType == VideoType.HdDvd) + if (VideoType == VideoType.BluRay || VideoType == VideoType.Dvd) { return System.IO.Path.GetFileName(Path); } @@ -395,18 +424,27 @@ namespace MediaBrowser.Controller.Entities return base.IsValidFromResolver(newItem); } - /// <summary> - /// Gets the playable stream files. - /// </summary> - /// <param name="rootPath">The root path.</param> - /// <returns>List{System.String}.</returns> - public List<string> GetPlayableStreamFiles(string rootPath) + public static string[] QueryPlayableStreamFiles(string rootPath, VideoType videoType) { - var allFiles = FileSystem.GetFilePaths(rootPath, true).ToList(); - - return PlayableStreamFileNames.Select(name => allFiles.FirstOrDefault(f => string.Equals(System.IO.Path.GetFileName(f), name, StringComparison.OrdinalIgnoreCase))) - .Where(f => !string.IsNullOrEmpty(f)) - .ToList(); + if (videoType == VideoType.Dvd) + { + return FileSystem.GetFiles(rootPath, new[] { ".vob" }, false, true) + .OrderByDescending(i => i.Length) + .ThenBy(i => i.FullName) + .Take(1) + .Select(i => i.FullName) + .ToArray(); + } + if (videoType == VideoType.BluRay) + { + return FileSystem.GetFiles(rootPath, new[] { ".m2ts" }, false, true) + .OrderByDescending(i => i.Length) + .ThenBy(i => i.FullName) + .Take(1) + .Select(i => i.FullName) + .ToArray(); + } + return new string[] { }; } /// <summary> @@ -500,7 +538,7 @@ namespace MediaBrowser.Controller.Entities public override IEnumerable<FileSystemMetadata> GetDeletePaths() { - if (!DetectIsInMixedFolder()) + if (!IsInMixedFolder) { return new[] { new FileSystemMetadata @@ -514,17 +552,12 @@ namespace MediaBrowser.Controller.Entities return base.GetDeletePaths(); } - public IEnumerable<MediaStream> GetMediaStreams() + public List<MediaStream> GetMediaStreams() { - var mediaSource = GetMediaSources(false) - .FirstOrDefault(); - - if (mediaSource == null) + return MediaSourceManager.GetMediaStreams(new MediaStreamQuery { - return new List<MediaStream>(); - } - - return mediaSource.MediaStreams; + ItemId = Id + }); } public virtual MediaStream GetDefaultVideoStream() @@ -572,7 +605,7 @@ namespace MediaBrowser.Controller.Entities return list; } - public virtual IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution) + public virtual List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution) { if (SourceType == SourceType.Channel) { @@ -593,6 +626,14 @@ namespace MediaBrowser.Controller.Entities var list = GetAllVideosForMediaSources(); var result = list.Select(i => GetVersionInfo(enablePathSubstitution, i.Item1, i.Item2)).ToList(); + if (IsActiveRecording()) + { + foreach (var mediaSource in result) + { + mediaSource.Type = MediaSourceType.Placeholder; + } + } + return result.OrderBy(i => { if (i.VideoType == VideoType.VideoFile) @@ -619,8 +660,7 @@ namespace MediaBrowser.Controller.Entities throw new ArgumentNullException("media"); } - var mediaStreams = MediaSourceManager.GetMediaStreams(media.Id) - .ToList(); + var mediaStreams = MediaSourceManager.GetMediaStreams(media.Id); var locationType = media.LocationType; @@ -639,7 +679,6 @@ namespace MediaBrowser.Controller.Entities Size = media.Size, Timestamp = media.Timestamp, Type = type, - PlayableStreamFileNames = media.PlayableStreamFileNames.ToList(), SupportsDirectStream = media.VideoType == VideoType.VideoFile, IsRemote = media.IsShortcut }; @@ -714,10 +753,6 @@ namespace MediaBrowser.Controller.Entities { terms.Add("DVD"); } - else if (video.VideoType == VideoType.HdDvd) - { - terms.Add("HD-DVD"); - } else if (video.VideoType == VideoType.Iso) { if (video.IsoType.HasValue) @@ -781,7 +816,7 @@ namespace MediaBrowser.Controller.Entities } } - return string.Join("/", terms.ToArray()); + return string.Join("/", terms.ToArray(terms.Count)); } } diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs index 61b1a3b1a..7d820b007 100644 --- a/MediaBrowser.Controller/Entities/Year.cs +++ b/MediaBrowser.Controller/Entities/Year.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.Linq; using MediaBrowser.Model.Serialization; namespace MediaBrowser.Controller.Entities |
