diff options
Diffstat (limited to 'MediaBrowser.Controller')
74 files changed, 849 insertions, 1390 deletions
diff --git a/MediaBrowser.Controller/Chapters/IChapterManager.cs b/MediaBrowser.Controller/Chapters/IChapterManager.cs index 05517ebcd..85feec40b 100644 --- a/MediaBrowser.Controller/Chapters/IChapterManager.cs +++ b/MediaBrowser.Controller/Chapters/IChapterManager.cs @@ -1,7 +1,5 @@ using System.Collections.Generic; -using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Chapters @@ -21,10 +19,6 @@ namespace MediaBrowser.Controller.Chapters /// <summary> /// Saves the chapters. /// </summary> - /// <param name="itemId">The item identifier.</param> - /// <param name="chapters">The chapters.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - Task SaveChapters(string itemId, List<ChapterInfo> chapters, CancellationToken cancellationToken); + Task SaveChapters(string itemId, List<ChapterInfo> chapters); } } diff --git a/MediaBrowser.Controller/Collections/ManualCollectionsFolder.cs b/MediaBrowser.Controller/Collections/ManualCollectionsFolder.cs index 160a788f1..38d2611f0 100644 --- a/MediaBrowser.Controller/Collections/ManualCollectionsFolder.cs +++ b/MediaBrowser.Controller/Collections/ManualCollectionsFolder.cs @@ -8,7 +8,6 @@ namespace MediaBrowser.Controller.Collections public ManualCollectionsFolder() { Name = "Collections"; - DisplayMediaType = "CollectionFolder"; } public override bool IsHidden diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index 2832462a8..29363f492 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -54,7 +54,7 @@ namespace MediaBrowser.Controller.Drawing /// <param name="item">The item.</param> /// <param name="imageType">Type of the image.</param> /// <returns>IEnumerable{IImageEnhancer}.</returns> - IEnumerable<IImageEnhancer> GetSupportedEnhancers(IHasImages item, ImageType imageType); + IEnumerable<IImageEnhancer> GetSupportedEnhancers(IHasMetadata item, ImageType imageType); /// <summary> /// Gets the image cache tag. @@ -62,7 +62,7 @@ namespace MediaBrowser.Controller.Drawing /// <param name="item">The item.</param> /// <param name="image">The image.</param> /// <returns>Guid.</returns> - string GetImageCacheTag(IHasImages item, ItemImageInfo image); + string GetImageCacheTag(IHasMetadata item, ItemImageInfo image); /// <summary> /// Gets the image cache tag. @@ -71,7 +71,7 @@ namespace MediaBrowser.Controller.Drawing /// <param name="image">The image.</param> /// <param name="imageEnhancers">The image enhancers.</param> /// <returns>Guid.</returns> - string GetImageCacheTag(IHasImages item, ItemImageInfo image, List<IImageEnhancer> imageEnhancers); + string GetImageCacheTag(IHasMetadata item, ItemImageInfo image, List<IImageEnhancer> imageEnhancers); /// <summary> /// Processes the image. @@ -95,7 +95,7 @@ namespace MediaBrowser.Controller.Drawing /// <param name="imageType">Type of the image.</param> /// <param name="imageIndex">Index of the image.</param> /// <returns>Task{System.String}.</returns> - Task<string> GetEnhancedImage(IHasImages item, ImageType imageType, int imageIndex); + Task<string> GetEnhancedImage(IHasMetadata item, ImageType imageType, int imageIndex); /// <summary> /// Gets the supported image output formats. diff --git a/MediaBrowser.Controller/Drawing/ImageHelper.cs b/MediaBrowser.Controller/Drawing/ImageHelper.cs index 54f2ff987..9452446a1 100644 --- a/MediaBrowser.Controller/Drawing/ImageHelper.cs +++ b/MediaBrowser.Controller/Drawing/ImageHelper.cs @@ -48,7 +48,7 @@ namespace MediaBrowser.Controller.Drawing return new ImageSize(widthValue, height); } - private static double GetEstimatedAspectRatio(ImageType type, IHasImages item) + private static double GetEstimatedAspectRatio(ImageType type, IHasMetadata item) { switch (type) { diff --git a/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs b/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs index cfb3a97ee..fac21c744 100644 --- a/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs +++ b/MediaBrowser.Controller/Drawing/ImageProcessingOptions.cs @@ -12,7 +12,7 @@ namespace MediaBrowser.Controller.Drawing { public string ItemId { get; set; } public string ItemType { get; set; } - public IHasImages Item { get; set; } + public IHasMetadata Item { get; set; } public ItemImageInfo Image { get; set; } diff --git a/MediaBrowser.Controller/Drawing/ImageProcessorExtensions.cs b/MediaBrowser.Controller/Drawing/ImageProcessorExtensions.cs index c5601c49f..5dfa94e1e 100644 --- a/MediaBrowser.Controller/Drawing/ImageProcessorExtensions.cs +++ b/MediaBrowser.Controller/Drawing/ImageProcessorExtensions.cs @@ -5,12 +5,12 @@ namespace MediaBrowser.Controller.Drawing { public static class ImageProcessorExtensions { - public static string GetImageCacheTag(this IImageProcessor processor, IHasImages item, ImageType imageType) + public static string GetImageCacheTag(this IImageProcessor processor, IHasMetadata item, ImageType imageType) { return processor.GetImageCacheTag(item, imageType, 0); } - public static string GetImageCacheTag(this IImageProcessor processor, IHasImages item, ImageType imageType, int imageIndex) + public static string GetImageCacheTag(this IImageProcessor processor, IHasMetadata item, ImageType imageType, int imageIndex) { var imageInfo = item.GetImageInfo(imageType, imageIndex); diff --git a/MediaBrowser.Controller/Dto/IDtoService.cs b/MediaBrowser.Controller/Dto/IDtoService.cs index a6f807ce9..963092f52 100644 --- a/MediaBrowser.Controller/Dto/IDtoService.cs +++ b/MediaBrowser.Controller/Dto/IDtoService.cs @@ -24,14 +24,14 @@ namespace MediaBrowser.Controller.Dto /// </summary> /// <param name="dto">The dto.</param> /// <param name="item">The item.</param> - void AttachPrimaryImageAspectRatio(IItemDto dto, IHasImages item); + void AttachPrimaryImageAspectRatio(IItemDto dto, IHasMetadata item); /// <summary> /// Gets the primary image aspect ratio. /// </summary> /// <param name="item">The item.</param> /// <returns>System.Nullable<System.Double>.</returns> - double? GetPrimaryImageAspectRatio(IHasImages item); + double? GetPrimaryImageAspectRatio(IHasMetadata item); /// <summary> /// Gets the base item dto. diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs index e8ebbdb70..f88522f78 100644 --- a/MediaBrowser.Controller/Entities/AggregateFolder.cs +++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs @@ -23,18 +23,6 @@ namespace MediaBrowser.Controller.Entities PhysicalLocationsList = new List<string>(); } - /// <summary> - /// We don't support manual shortcuts - /// </summary> - [IgnoreDataMember] - protected override bool SupportsShortcutChildren - { - get - { - return false; - } - } - [IgnoreDataMember] public override bool IsPhysicalRoot { @@ -80,9 +68,9 @@ namespace MediaBrowser.Controller.Entities public List<string> PhysicalLocationsList { get; set; } - protected override IEnumerable<FileSystemMetadata> GetFileSystemChildren(IDirectoryService directoryService) + protected override FileSystemMetadata[] GetFileSystemChildren(IDirectoryService directoryService) { - return CreateResolveArgs(directoryService, true).FileSystemChildren; + return CreateResolveArgs(directoryService, true).FileSystemChildren.ToArray(); } private List<Guid> _childrenIds = null; diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index 873ac3104..0781dc35b 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> + [IgnoreDataMember] public List<string> Artists { get; set; } - public List<string> AlbumArtists { get; set; } + [IgnoreDataMember] + public string[] AlbumArtists { get; set; } [IgnoreDataMember] public override bool EnableRefreshOnDateModifiedChange @@ -40,7 +43,7 @@ namespace MediaBrowser.Controller.Entities.Audio public Audio() { Artists = new List<string>(); - AlbumArtists = new List<string>(); + AlbumArtists = EmptyStringArray; } public override double? GetDefaultPrimaryImageAspectRatio() @@ -193,6 +196,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 +224,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 +268,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..6900699e5 100644 --- a/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs @@ -5,7 +5,7 @@ namespace MediaBrowser.Controller.Entities.Audio { public interface IHasAlbumArtist { - List<string> AlbumArtists { get; set; } + string[] AlbumArtists { get; set; } } public interface IHasArtist diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index 516ab5053..c35e81826 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -19,13 +19,13 @@ namespace MediaBrowser.Controller.Entities.Audio /// </summary> public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo<AlbumInfo>, IMetadataContainer { - public List<string> AlbumArtists { get; set; } + public string[] AlbumArtists { get; set; } public List<string> Artists { get; set; } public MusicAlbum() { Artists = new List<string>(); - AlbumArtists = new List<string>(); + AlbumArtists = EmptyStringArray; } [IgnoreDataMember] diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index 7a37b2e02..559806ac4 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -212,7 +212,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 songs = items.OfType<Audio>().ToList(); diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index b4a3d89ea..8cc90db7d 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -39,21 +39,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>(); - Keywords = new List<string>(); - 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 = { '?', '/', '&' }; @@ -74,8 +79,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; } @@ -88,7 +95,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; } @@ -130,12 +138,6 @@ namespace MediaBrowser.Controller.Entities public bool IsInMixedFolder { get; set; } [IgnoreDataMember] - protected virtual bool SupportsIsInMixedFolderDetection - { - get { return false; } - } - - [IgnoreDataMember] public virtual bool SupportsPlayedStatus { get @@ -153,16 +155,6 @@ namespace MediaBrowser.Controller.Entities } } - public bool DetectIsInMixedFolder() - { - if (SupportsIsInMixedFolderDetection) - { - - } - - return IsInMixedFolder; - } - [IgnoreDataMember] public virtual bool SupportsRemoteImageDownloading { @@ -214,7 +206,9 @@ namespace MediaBrowser.Controller.Entities get { return PremiereDate.HasValue && PremiereDate.Value.ToLocalTime().Date >= DateTime.Now.Date; } } + [IgnoreDataMember] public int? TotalBitrate { get; set; } + [IgnoreDataMember] public ExtraType? ExtraType { get; set; } [IgnoreDataMember] @@ -560,7 +554,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. @@ -820,13 +814,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> @@ -836,9 +823,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> @@ -865,7 +849,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. @@ -879,10 +863,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> Keywords { get; set; } - public List<string> ProductionLocations { get; set; } + [IgnoreDataMember] + public string[] ProductionLocations { get; set; } /// <summary> /// Gets or sets the home page URL. @@ -991,11 +975,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 @@ -1020,18 +1004,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>() @@ -1050,7 +1034,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) @@ -1158,7 +1142,7 @@ namespace MediaBrowser.Controller.Entities { if (SupportsThemeMedia) { - if (!DetectIsInMixedFolder()) + if (!IsInMixedFolder) { themeSongsChanged = await RefreshThemeSongs(this, options, fileSystemChildren, cancellationToken).ConfigureAwait(false); @@ -1176,7 +1160,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; @@ -1187,7 +1171,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); @@ -1202,9 +1186,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); @@ -1233,8 +1217,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); @@ -1313,12 +1297,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; @@ -1739,12 +1720,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> @@ -1864,10 +1861,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) @@ -1881,7 +1886,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 { @@ -1922,7 +1930,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) @@ -1939,7 +1952,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 @@ -1948,7 +1961,7 @@ namespace MediaBrowser.Controller.Entities if (deletedImages.Count > 0) { - ImageInfos = ImageInfos.Except(deletedImages).ToList(); + ImageInfos = ImageInfos.Except(deletedImages).ToArray(); } return deletedImages.Count > 0; @@ -2068,10 +2081,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; } @@ -2112,7 +2140,7 @@ namespace MediaBrowser.Controller.Entities var extensions = new[] { ".nfo", ".xml", ".srt" }.ToList(); extensions.AddRange(SupportedImageExtensionsList); - 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(); } @@ -2272,17 +2300,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(); - } - if (!item.Keywords.SequenceEqual(ownedItem.Keywords, StringComparer.Ordinal)) - { - newOptions.ForceSave = true; - ownedItem.Keywords = item.Keywords.ToList(); + ownedItem.ProductionLocations = item.ProductionLocations; } if (item.CommunityRating != ownedItem.CommunityRating) { @@ -2341,7 +2364,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) diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index d88b7da34..d02e469d4 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -32,15 +32,6 @@ namespace MediaBrowser.Controller.Entities } [IgnoreDataMember] - protected override bool SupportsShortcutChildren - { - get - { - return true; - } - } - - [IgnoreDataMember] public override bool SupportsPlayedStatus { get @@ -165,9 +156,9 @@ namespace MediaBrowser.Controller.Entities public List<string> PhysicalLocationsList { get; set; } public List<Guid> PhysicalFolderIds { get; set; } - protected override IEnumerable<FileSystemMetadata> GetFileSystemChildren(IDirectoryService directoryService) + protected override FileSystemMetadata[] GetFileSystemChildren(IDirectoryService directoryService) { - return CreateResolveArgs(directoryService, true).FileSystemChildren; + return CreateResolveArgs(directoryService, true).FileSystemChildren.ToArray(); } private bool _requiresRefresh; @@ -249,7 +240,7 @@ 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(); 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..46ae9230b 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] @@ -706,7 +707,7 @@ namespace MediaBrowser.Controller.Entities public virtual int GetChildCount(User user) { - if (LinkedChildren.Count > 0) + if (LinkedChildren.Length > 0) { if (!(this is ICollectionFolder)) { @@ -791,7 +792,7 @@ namespace MediaBrowser.Controller.Entities query.StartIndex = null; query.Limit = null; - var itemsList = LibraryManager.GetItemList(query); + IEnumerable<BaseItem> itemsList = LibraryManager.GetItemList(query); var user = query.User; if (user != null) @@ -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"); @@ -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.SortBy.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) @@ -1203,7 +1219,7 @@ namespace MediaBrowser.Controller.Entities return GetLinkedChildren(); } - if (LinkedChildren.Count == 0) + if (LinkedChildren.Length == 0) { return new List<BaseItem>(); } @@ -1292,14 +1308,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 +1341,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) @@ -1370,15 +1382,15 @@ 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)); + var tasks = itemsResult.Select(c => c.MarkPlayed(user, datePlayed, resetPosition)); await Task.WhenAll(tasks).ConfigureAwait(false); } @@ -1390,7 +1402,7 @@ namespace MediaBrowser.Controller.Entities /// <returns>Task.</returns> public override async Task MarkUnplayed(User user) { - var itemsResult = GetItems(new InternalItemsQuery + var itemsResult = GetItemList(new InternalItemsQuery { User = user, Recursive = true, @@ -1400,14 +1412,14 @@ namespace MediaBrowser.Controller.Entities }); // Sweep through recursively and update status - var tasks = itemsResult.Items.Select(c => c.MarkUnplayed(user)); + var tasks = itemsResult.Select(c => c.MarkUnplayed(user)); await Task.WhenAll(tasks).ConfigureAwait(false); } public override bool IsPlayed(User user) { - var itemsResult = GetItems(new InternalItemsQuery(user) + var itemsResult = GetItemList(new InternalItemsQuery(user) { Recursive = true, IsFolder = false, @@ -1416,7 +1428,7 @@ namespace MediaBrowser.Controller.Entities }); - return itemsResult.Items + return itemsResult .All(i => i.IsPlayed(user)); } diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs index baefc9dfa..eb2638ee4 100644 --- a/MediaBrowser.Controller/Entities/Game.cs +++ b/MediaBrowser.Controller/Entities/Game.cs @@ -13,14 +13,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 +45,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 +84,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 +100,7 @@ namespace MediaBrowser.Controller.Entities public override IEnumerable<FileSystemMetadata> GetDeletePaths() { - if (!DetectIsInMixedFolder()) + if (!IsInMixedFolder) { return new[] { new FileSystemMetadata @@ -127,16 +127,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/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..bf4acdfbd 100644 --- a/MediaBrowser.Controller/Entities/IHasMediaSources.cs +++ b/MediaBrowser.Controller/Entities/IHasMediaSources.cs @@ -1,5 +1,6 @@ using MediaBrowser.Model.Dto; using System.Collections.Generic; +using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Entities { @@ -10,6 +11,7 @@ namespace MediaBrowser.Controller.Entities /// </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..ce4a482ba 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,7 +9,7 @@ namespace MediaBrowser.Controller.Entities /// <summary> /// Interface IHasUserData /// </summary> - public interface IHasUserData : IHasId + public interface IHasUserData { List<string> GetUserDataKeys(); @@ -20,5 +21,7 @@ namespace MediaBrowser.Controller.Entities bool EnableRememberingTrackSelections { get; } bool SupportsPlayedStatus { get; } + + Guid Id { get; } } } diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index 608e3f56c..04833d049 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -38,12 +38,10 @@ namespace MediaBrowser.Controller.Entities public string[] ExcludeTags { get; set; } public string[] ExcludeInheritedTags { get; set; } public string[] Genres { get; set; } - public string[] Keywords { get; set; } 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; } @@ -150,7 +148,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; } @@ -162,6 +159,7 @@ 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; } @@ -194,7 +192,6 @@ namespace MediaBrowser.Controller.Entities OfficialRatings = new string[] { }; SortBy = new string[] { }; MediaTypes = new string[] { }; - Keywords = new string[] { }; IncludeItemTypes = new string[] { }; ExcludeItemTypes = new string[] { }; Genres = new string[] { }; @@ -215,7 +212,6 @@ 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>>(); } diff --git a/MediaBrowser.Controller/Entities/KeywordExtensions.cs b/MediaBrowser.Controller/Entities/KeywordExtensions.cs deleted file mode 100644 index 5c9afdf3d..000000000 --- a/MediaBrowser.Controller/Entities/KeywordExtensions.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Linq; - -namespace MediaBrowser.Controller.Entities -{ - public static class KeywordExtensions - { - public static void AddKeyword(this BaseItem item, string name) - { - if (string.IsNullOrWhiteSpace(name)) - { - throw new ArgumentNullException("name"); - } - - if (!item.Keywords.Contains(name, StringComparer.OrdinalIgnoreCase)) - { - item.Keywords.Add(name); - } - } - } -} diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index 071ed405f..6ba9577d1 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -21,9 +21,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 +47,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. @@ -116,7 +116,7 @@ namespace MediaBrowser.Controller.Entities.Movies { if (IsLegacyBoxSet) { - return true; + return false; } return false; @@ -148,17 +148,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> 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..2028c1c3b 100644 --- a/MediaBrowser.Controller/Entities/MusicVideo.cs +++ b/MediaBrowser.Controller/Entities/MusicVideo.cs @@ -8,6 +8,7 @@ namespace MediaBrowser.Controller.Entities { public class MusicVideo : Video, IHasArtist, IHasMusicGenres, IHasLookupInfo<MusicVideoInfo> { + [IgnoreDataMember] public List<string> Artists { get; set; } public MusicVideo() @@ -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/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/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 8b73b80b0..3350a6579 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. @@ -193,7 +185,7 @@ namespace MediaBrowser.Controller.Entities.TV 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,17 +217,6 @@ 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 { @@ -273,18 +254,10 @@ namespace MediaBrowser.Controller.Entities.TV query.IncludeItemTypes = new[] { typeof(Season).Name }; query.SortBy = new[] {ItemSortBy.SortName}; - 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) @@ -332,27 +305,18 @@ namespace MediaBrowser.Controller.Entities.TV 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 allSeriesEpisodes = allItems.OfType<Episode>(); 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 seasons = items.OfType<Season>().ToList(); - var otherItems = items.Except(seasons).ToList(); + var items = GetRecursiveChildren(); - 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; @@ -445,18 +416,10 @@ namespace MediaBrowser.Controller.Entities.TV 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>(); 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 b4a142a8e..c5144aadf 100644 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ b/MediaBrowser.Controller/Entities/Trailer.cs @@ -15,7 +15,6 @@ namespace MediaBrowser.Controller.Entities public Trailer() { RemoteTrailers = new List<MediaUrl>(); - Keywords = new List<string>(); TrailerTypes = new List<TrailerType> { TrailerType.LocalTrailer }; } @@ -48,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); } @@ -74,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/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index 0d2d69c94..4c44a613b 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -82,7 +82,7 @@ namespace MediaBrowser.Controller.Entities public override IEnumerable<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; } 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..9323404e3 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -779,7 +779,6 @@ namespace MediaBrowser.Controller.Entities items = FilterVirtualEpisodes(items, query.IsMissing, - query.IsVirtualUnaired, query.IsUnaired); if (collapseBoxSetItems && user != null) @@ -1065,7 +1064,6 @@ namespace MediaBrowser.Controller.Entities private static IEnumerable<BaseItem> FilterVirtualEpisodes( IEnumerable<BaseItem> items, bool? isMissing, - bool? isVirtualUnaired, bool? isUnaired) { if (isMissing.HasValue) @@ -1096,20 +1094,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; } @@ -1387,8 +1371,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 +1447,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 +1460,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 +1658,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)); diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index c5d9b9203..fbeefbbd9 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 @@ -52,6 +53,12 @@ namespace MediaBrowser.Controller.Entities } } + /// <summary> + /// Gets or sets the display type of the media. + /// </summary> + /// <value>The display type of the media.</value> + public string DisplayMediaType { get; set; } + [IgnoreDataMember] public override bool SupportsPositionTicksResume { @@ -77,15 +84,6 @@ namespace MediaBrowser.Controller.Entities } } - [IgnoreDataMember] - protected override bool SupportsIsInMixedFolderDetection - { - get - { - return true; - } - } - public override string CreatePresentationUniqueKey() { if (!string.IsNullOrWhiteSpace(PrimaryVersionId)) @@ -121,7 +119,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. @@ -158,11 +156,6 @@ namespace MediaBrowser.Controller.Entities 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> @@ -171,6 +164,11 @@ namespace MediaBrowser.Controller.Entities return GetPlayableStreamFiles(Path); } + public List<string> GetPlayableStreamFileNames() + { + return GetPlayableStreamFiles().Select(System.IO.Path.GetFileName).ToList(); ; + } + /// <summary> /// Gets or sets the aspect ratio. /// </summary> @@ -179,17 +177,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 +214,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() @@ -339,8 +335,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 +352,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); } @@ -402,13 +397,52 @@ namespace MediaBrowser.Controller.Entities /// <returns>List{System.String}.</returns> public List<string> GetPlayableStreamFiles(string rootPath) { + if (VideoType == VideoType.VideoFile) + { + return new List<string>(); + } + var allFiles = FileSystem.GetFilePaths(rootPath, true).ToList(); - return PlayableStreamFileNames.Select(name => allFiles.FirstOrDefault(f => string.Equals(System.IO.Path.GetFileName(f), name, StringComparison.OrdinalIgnoreCase))) + 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; + } + + return QueryPlayableStreamFiles(rootPath, videoType).Select(name => allFiles.FirstOrDefault(f => string.Equals(System.IO.Path.GetFileName(f), name, StringComparison.OrdinalIgnoreCase))) .Where(f => !string.IsNullOrEmpty(f)) .ToList(); } + public static List<string> QueryPlayableStreamFiles(string rootPath, VideoType videoType) + { + 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) + .ToList(); + } + 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) + .ToList(); + } + return new List<string>(); + } + /// <summary> /// Gets a value indicating whether [is3 D]. /// </summary> @@ -500,7 +534,7 @@ namespace MediaBrowser.Controller.Entities public override IEnumerable<FileSystemMetadata> GetDeletePaths() { - if (!DetectIsInMixedFolder()) + if (!IsInMixedFolder) { return new[] { new FileSystemMetadata @@ -514,17 +548,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 +601,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) { @@ -619,8 +648,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 +667,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 +741,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 +804,7 @@ namespace MediaBrowser.Controller.Entities } } - return string.Join("/", terms.ToArray()); + return string.Join("/", terms.ToArray(terms.Count)); } } diff --git a/MediaBrowser.Controller/FileOrganization/IFileOrganizationService.cs b/MediaBrowser.Controller/FileOrganization/IFileOrganizationService.cs deleted file mode 100644 index 9a5b96a24..000000000 --- a/MediaBrowser.Controller/FileOrganization/IFileOrganizationService.cs +++ /dev/null @@ -1,107 +0,0 @@ -using MediaBrowser.Model.Events; -using MediaBrowser.Model.FileOrganization; -using MediaBrowser.Model.Querying; -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Controller.FileOrganization -{ - public interface IFileOrganizationService - { - event EventHandler<GenericEventArgs<FileOrganizationResult>> ItemAdded; - event EventHandler<GenericEventArgs<FileOrganizationResult>> ItemUpdated; - event EventHandler<GenericEventArgs<FileOrganizationResult>> ItemRemoved; - event EventHandler LogReset; - - /// <summary> - /// Processes the new files. - /// </summary> - void BeginProcessNewFiles(); - - /// <summary> - /// Deletes the original file. - /// </summary> - /// <param name="resultId">The result identifier.</param> - /// <returns>Task.</returns> - Task DeleteOriginalFile(string resultId); - - /// <summary> - /// Clears the log. - /// </summary> - /// <returns>Task.</returns> - Task ClearLog(); - - /// <summary> - /// Performs the organization. - /// </summary> - /// <param name="resultId">The result identifier.</param> - /// <returns>Task.</returns> - Task PerformOrganization(string resultId); - - /// <summary> - /// Performs the episode organization. - /// </summary> - /// <param name="request">The request.</param> - /// <returns>Task.</returns> - Task PerformEpisodeOrganization(EpisodeFileOrganizationRequest request); - - /// <summary> - /// Gets the results. - /// </summary> - /// <param name="query">The query.</param> - /// <returns>IEnumerable{FileOrganizationResult}.</returns> - QueryResult<FileOrganizationResult> GetResults(FileOrganizationResultQuery query); - - /// <summary> - /// Gets the result. - /// </summary> - /// <param name="id">The identifier.</param> - /// <returns>FileOrganizationResult.</returns> - FileOrganizationResult GetResult(string id); - - /// <summary> - /// Gets the result by source path. - /// </summary> - /// <param name="path">The path.</param> - /// <returns>FileOrganizationResult.</returns> - FileOrganizationResult GetResultBySourcePath(string path); - - /// <summary> - /// Saves the result. - /// </summary> - /// <param name="result">The result.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - Task SaveResult(FileOrganizationResult result, CancellationToken cancellationToken); - - /// <summary> - /// Returns a list of smart match entries - /// </summary> - /// <param name="query">The query.</param> - /// <returns>IEnumerable{SmartMatchInfo}.</returns> - QueryResult<SmartMatchInfo> GetSmartMatchInfos(FileOrganizationResultQuery query); - - /// <summary> - /// Deletes a smart match entry. - /// </summary> - /// <param name="ItemName">Item name.</param> - /// <param name="matchString">The match string to delete.</param> - void DeleteSmartMatchEntry(string ItemName, string matchString); - - /// <summary> - /// Attempts to add a an item to the list of currently processed items. - /// </summary> - /// <param name="result">The result item.</param> - /// <param name="fullClientRefresh">Passing true will notify the client to reload all items, otherwise only a single item will be refreshed.</param> - /// <returns>True if the item was added, False if the item is already contained in the list.</returns> - bool AddToInProgressList(FileOrganizationResult result, bool fullClientRefresh); - - /// <summary> - /// Removes an item from the list of currently processed items. - /// </summary> - /// <param name="result">The result item.</param> - /// <returns>True if the item was removed, False if the item was not contained in the list.</returns> - bool RemoveFromInprogressList(FileOrganizationResult result); - } -} diff --git a/MediaBrowser.Controller/IO/FileData.cs b/MediaBrowser.Controller/IO/FileData.cs index 97b778d0c..64a7610fe 100644 --- a/MediaBrowser.Controller/IO/FileData.cs +++ b/MediaBrowser.Controller/IO/FileData.cs @@ -13,6 +13,17 @@ namespace MediaBrowser.Controller.IO /// </summary> public static class FileData { + private static Dictionary<string, FileSystemMetadata> GetFileSystemDictionary(FileSystemMetadata[] list) + { + var dict = new Dictionary<string, FileSystemMetadata>(StringComparer.OrdinalIgnoreCase); + + foreach (var file in list) + { + dict[file.FullName] = file; + } + return dict; + } + /// <summary> /// Gets the filtered file system entries. /// </summary> @@ -42,13 +53,13 @@ namespace MediaBrowser.Controller.IO throw new ArgumentNullException("args"); } + var entries = directoryService.GetFileSystemEntries(path); + if (!resolveShortcuts && flattenFolderDepth == 0) { - return directoryService.GetFileSystemDictionary(path); + return GetFileSystemDictionary(entries); } - var entries = directoryService.GetFileSystemEntries(path); - var dict = new Dictionary<string, FileSystemMetadata>(StringComparer.OrdinalIgnoreCase); foreach (var entry in entries) diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index b726c267c..025254d4b 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -185,13 +185,6 @@ namespace MediaBrowser.Controller.Library SortOrder sortOrder); /// <summary> - /// Ensure supplied item has only one instance throughout - /// </summary> - /// <param name="item">The item.</param> - /// <returns>The proper instance to the item</returns> - BaseItem GetOrAddByReferenceItem(BaseItem item); - - /// <summary> /// Gets the user root folder. /// </summary> /// <returns>UserRootFolder.</returns> @@ -520,21 +513,21 @@ namespace MediaBrowser.Controller.Library /// <param name="image">The image.</param> /// <param name="imageIndex">Index of the image.</param> /// <returns>Task.</returns> - Task<ItemImageInfo> ConvertImageToLocal(IHasImages item, ItemImageInfo image, int imageIndex); + Task<ItemImageInfo> ConvertImageToLocal(IHasMetadata item, ItemImageInfo image, int imageIndex); /// <summary> /// Gets the items. /// </summary> /// <param name="query">The query.</param> /// <returns>QueryResult<BaseItem>.</returns> - IEnumerable<BaseItem> GetItemList(InternalItemsQuery query); + List<BaseItem> GetItemList(InternalItemsQuery query); - IEnumerable<BaseItem> GetItemList(InternalItemsQuery query, bool allowExternalContent); + List<BaseItem> GetItemList(InternalItemsQuery query, bool allowExternalContent); /// <summary> /// Gets the items. /// </summary> - IEnumerable<BaseItem> GetItemList(InternalItemsQuery query, List<BaseItem> parents); + List<BaseItem> GetItemList(InternalItemsQuery query, List<BaseItem> parents); /// <summary> /// Gets the items result. diff --git a/MediaBrowser.Controller/Library/IMediaSourceManager.cs b/MediaBrowser.Controller/Library/IMediaSourceManager.cs index 2f8f37789..204033e1d 100644 --- a/MediaBrowser.Controller/Library/IMediaSourceManager.cs +++ b/MediaBrowser.Controller/Library/IMediaSourceManager.cs @@ -24,19 +24,19 @@ namespace MediaBrowser.Controller.Library /// </summary> /// <param name="itemId">The item identifier.</param> /// <returns>IEnumerable<MediaStream>.</returns> - IEnumerable<MediaStream> GetMediaStreams(Guid itemId); + List<MediaStream> GetMediaStreams(Guid itemId); /// <summary> /// Gets the media streams. /// </summary> /// <param name="mediaSourceId">The media source identifier.</param> /// <returns>IEnumerable<MediaStream>.</returns> - IEnumerable<MediaStream> GetMediaStreams(string mediaSourceId); + List<MediaStream> GetMediaStreams(string mediaSourceId); /// <summary> /// Gets the media streams. /// </summary> /// <param name="query">The query.</param> /// <returns>IEnumerable<MediaStream>.</returns> - IEnumerable<MediaStream> GetMediaStreams(MediaStreamQuery query); + List<MediaStream> GetMediaStreams(MediaStreamQuery query); /// <summary> /// Gets the playack media sources. @@ -56,7 +56,7 @@ namespace MediaBrowser.Controller.Library /// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param> /// <param name="user">The user.</param> /// <returns>IEnumerable<MediaSourceInfo>.</returns> - IEnumerable<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution, User user = null); + List<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution, User user = null); /// <summary> /// Gets the static media source. diff --git a/MediaBrowser.Controller/Library/IMusicManager.cs b/MediaBrowser.Controller/Library/IMusicManager.cs index 95ba671b4..535e6df7e 100644 --- a/MediaBrowser.Controller/Library/IMusicManager.cs +++ b/MediaBrowser.Controller/Library/IMusicManager.cs @@ -10,16 +10,16 @@ namespace MediaBrowser.Controller.Library /// <summary> /// Gets the instant mix from song. /// </summary> - IEnumerable<Audio> GetInstantMixFromItem(BaseItem item, User user, DtoOptions dtoOptions); - + List<BaseItem> GetInstantMixFromItem(BaseItem item, User user, DtoOptions dtoOptions); + /// <summary> /// Gets the instant mix from artist. /// </summary> - IEnumerable<Audio> GetInstantMixFromArtist(MusicArtist artist, User user, DtoOptions dtoOptions); - + List<BaseItem> GetInstantMixFromArtist(MusicArtist artist, User user, DtoOptions dtoOptions); + /// <summary> /// Gets the instant mix from genre. /// </summary> - IEnumerable<Audio> GetInstantMixFromGenres(IEnumerable<string> genres, User user, DtoOptions dtoOptions); + List<BaseItem> GetInstantMixFromGenres(IEnumerable<string> genres, User user, DtoOptions dtoOptions); } } diff --git a/MediaBrowser.Controller/Library/ItemResolveArgs.cs b/MediaBrowser.Controller/Library/ItemResolveArgs.cs index 3ddda81cd..76b6d8768 100644 --- a/MediaBrowser.Controller/Library/ItemResolveArgs.cs +++ b/MediaBrowser.Controller/Library/ItemResolveArgs.cs @@ -238,21 +238,6 @@ namespace MediaBrowser.Controller.Library } /// <summary> - /// Determines whether [contains meta file by name] [the specified name]. - /// </summary> - /// <param name="name">The name.</param> - /// <returns><c>true</c> if [contains meta file by name] [the specified name]; otherwise, <c>false</c>.</returns> - public bool ContainsMetaFileByName(string name) - { - if (string.IsNullOrEmpty(name)) - { - throw new ArgumentNullException(); - } - - return GetFileSystemEntryByName(name) != null; - } - - /// <summary> /// Determines whether [contains file system entry by name] [the specified name]. /// </summary> /// <param name="name">The name.</param> diff --git a/MediaBrowser.Controller/Library/TVUtils.cs b/MediaBrowser.Controller/Library/TVUtils.cs index 29421ebaf..7c82ec293 100644 --- a/MediaBrowser.Controller/Library/TVUtils.cs +++ b/MediaBrowser.Controller/Library/TVUtils.cs @@ -22,13 +22,13 @@ namespace MediaBrowser.Controller.Library /// </summary> /// <param name="day">The day.</param> /// <returns>List{DayOfWeek}.</returns> - public static List<DayOfWeek> GetAirDays(string day) + public static DayOfWeek[] GetAirDays(string day) { if (!string.IsNullOrWhiteSpace(day)) { if (day.Equals("Daily", StringComparison.OrdinalIgnoreCase)) { - return new List<DayOfWeek> + return new DayOfWeek[] { DayOfWeek.Sunday, DayOfWeek.Monday, @@ -44,13 +44,13 @@ namespace MediaBrowser.Controller.Library if (Enum.TryParse(day, true, out value)) { - return new List<DayOfWeek> + return new DayOfWeek[] { value }; } - return new List<DayOfWeek>(); + return new DayOfWeek[]{}; } return null; } diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index 288b30278..d6855b792 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -284,7 +284,7 @@ namespace MediaBrowser.Controller.LiveTv /// <summary> /// Gets the internal channels. /// </summary> - Task<QueryResult<LiveTvChannel>> GetInternalChannels(LiveTvChannelQuery query, DtoOptions dtoOptions, CancellationToken cancellationToken); + Task<QueryResult<BaseItem>> GetInternalChannels(LiveTvChannelQuery query, DtoOptions dtoOptions, CancellationToken cancellationToken); /// <summary> /// Gets the internal recordings. diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs b/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs index 1bbd1a008..27ff334ee 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvRecording.cs @@ -9,7 +9,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Controller.LiveTv { - public interface ILiveTvRecording : IHasImages, IHasMediaSources, IHasUserData, IHasStartDate, IHasProgramAttributes + public interface ILiveTvRecording : IHasMetadata, IHasMediaSources, IHasUserData, IHasStartDate, IHasProgramAttributes { string ServiceName { get; set; } string ExternalId { get; set; } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs index 9f8234402..25bc10dec 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs @@ -151,9 +151,9 @@ namespace MediaBrowser.Controller.LiveTv return user.Policy.EnableLiveTvManagement; } - public override IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution) + public override List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution) { - var list = base.GetMediaSources(enablePathSubstitution).ToList(); + var list = base.GetMediaSources(enablePathSubstitution); foreach (var mediaSource in list) { diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs index 898ea9ff4..4a93d0399 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs @@ -122,7 +122,7 @@ namespace MediaBrowser.Controller.LiveTv return new List<BaseItem>(); } - public IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution) + public List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution) { var list = new List<MediaSourceInfo>(); @@ -144,6 +144,11 @@ namespace MediaBrowser.Controller.LiveTv return list; } + public List<MediaStream> GetMediaStreams() + { + return new List<MediaStream>(); + } + protected override string GetInternalMetadataPath(string basePath) { return System.IO.Path.Combine(basePath, "livetv", Id.ToString("N"), "metadata"); diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index 9f55a9ff2..3efbc41f1 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -48,22 +48,19 @@ namespace MediaBrowser.Controller.LiveTv return list; } + private static string EmbyServiceName = "Emby"; public override double? GetDefaultPrimaryImageAspectRatio() { - if (IsMovie) + var serviceName = ServiceName; + if (!IsMovie && !string.Equals(serviceName, EmbyServiceName, StringComparison.OrdinalIgnoreCase) || !string.IsNullOrWhiteSpace(serviceName)) { - double value = 2; - value /= 3; - - return value; + return null; } - else - { - double value = 2; - value /= 3; - return value; - } + double value = 2; + value /= 3; + + return value; } [IgnoreDataMember] @@ -227,7 +224,7 @@ namespace MediaBrowser.Controller.LiveTv public LiveTvProgramLookupInfo GetLookupInfo() { var info = GetItemLookupInfo<LiveTvProgramLookupInfo>(); - info.IsMovie = IsMovie; + info.IsMovie = IsMovie; return info; } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs index c29d3dc47..2c26d3556 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs @@ -54,15 +54,6 @@ namespace MediaBrowser.Controller.LiveTv } [IgnoreDataMember] - protected override bool SupportsIsInMixedFolderDetection - { - get - { - return false; - } - } - - [IgnoreDataMember] public override bool SupportsPlayedStatus { get @@ -159,9 +150,9 @@ namespace MediaBrowser.Controller.LiveTv return user.Policy.EnableLiveTvManagement; } - public override IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution) + public override List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution) { - var list = base.GetMediaSources(enablePathSubstitution).ToList(); + var list = base.GetMediaSources(enablePathSubstitution); foreach (var mediaSource in list) { diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 22f94695d..26766f51a 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -99,9 +99,6 @@ <Compile Include="Entities\GameSystem.cs" /> <Compile Include="Entities\IHasAspectRatio.cs" /> <Compile Include="Entities\IHasDisplayOrder.cs" /> - <Compile Include="Entities\IHasId.cs" /> - <Compile Include="Entities\IHasImages.cs" /> - <Compile Include="Entities\KeywordExtensions.cs" /> <Compile Include="Entities\IHasMediaSources.cs" /> <Compile Include="Entities\IHasProgramAttributes.cs" /> <Compile Include="Entities\IHasScreenshots.cs" /> @@ -129,7 +126,6 @@ <Compile Include="Entities\UserView.cs" /> <Compile Include="Entities\UserViewBuilder.cs" /> <Compile Include="Extensions\StringExtensions.cs" /> - <Compile Include="FileOrganization\IFileOrganizationService.cs" /> <Compile Include="IO\StreamHelper.cs" /> <Compile Include="Library\DeleteOptions.cs" /> <Compile Include="Library\ILibraryPostScanTask.cs" /> @@ -170,7 +166,6 @@ <Compile Include="LiveTv\TimerEventInfo.cs" /> <Compile Include="LiveTv\TimerInfo.cs" /> <Compile Include="LiveTv\TunerChannelMapping.cs" /> - <Compile Include="MediaEncoding\ChapterImageRefreshOptions.cs" /> <Compile Include="MediaEncoding\EncodingHelper.cs" /> <Compile Include="MediaEncoding\EncodingJobInfo.cs" /> <Compile Include="MediaEncoding\EncodingJobOptions.cs" /> @@ -178,7 +173,6 @@ <Compile Include="MediaEncoding\ImageEncodingOptions.cs" /> <Compile Include="MediaEncoding\IMediaEncoder.cs" /> <Compile Include="MediaEncoding\ISubtitleEncoder.cs" /> - <Compile Include="MediaEncoding\JobLogger.cs" /> <Compile Include="MediaEncoding\MediaInfoRequest.cs" /> <Compile Include="MediaEncoding\MediaStreamSelector.cs" /> <Compile Include="Net\AuthenticatedAttribute.cs" /> @@ -206,7 +200,6 @@ <Compile Include="Notifications\INotificationTypeFactory.cs" /> <Compile Include="Notifications\NotificationUpdateEventArgs.cs" /> <Compile Include="Notifications\UserNotification.cs" /> - <Compile Include="Persistence\IFileOrganizationRepository.cs" /> <Compile Include="Persistence\MediaStreamQuery.cs" /> <Compile Include="Playlists\IPlaylistManager.cs" /> <Compile Include="Playlists\Playlist.cs" /> @@ -342,7 +335,6 @@ <Compile Include="Sync\ISyncDataProvider.cs" /> <Compile Include="Sync\ISyncManager.cs" /> <Compile Include="Sync\ISyncProvider.cs" /> - <Compile Include="Sync\ISyncRepository.cs" /> <Compile Include="Sync\SyncedFileInfo.cs" /> <Compile Include="Sync\SyncedItemProgress.cs" /> <Compile Include="TV\ITVSeriesManager.cs" /> diff --git a/MediaBrowser.Controller/MediaEncoding/ChapterImageRefreshOptions.cs b/MediaBrowser.Controller/MediaEncoding/ChapterImageRefreshOptions.cs deleted file mode 100644 index e11bd6cdf..000000000 --- a/MediaBrowser.Controller/MediaEncoding/ChapterImageRefreshOptions.cs +++ /dev/null @@ -1,17 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Model.Entities; -using System.Collections.Generic; - -namespace MediaBrowser.Controller.MediaEncoding -{ - public class ChapterImageRefreshOptions - { - public Video Video { get; set; } - - public List<ChapterInfo> Chapters { get; set; } - - public bool SaveChapters { get; set; } - - public bool ExtractImages { get; set; } - } -} diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 44bdafc5b..823c893ea 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -4,13 +4,14 @@ using System.Globalization; using System.IO; using System.Linq; using System.Threading; -using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; +using MediaBrowser.Model.Extensions; namespace MediaBrowser.Controller.MediaEncoding { @@ -19,14 +20,12 @@ namespace MediaBrowser.Controller.MediaEncoding private readonly CultureInfo _usCulture = new CultureInfo("en-US"); private readonly IMediaEncoder _mediaEncoder; - private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; private readonly ISubtitleEncoder _subtitleEncoder; - public EncodingHelper(IMediaEncoder mediaEncoder, IServerConfigurationManager config, IFileSystem fileSystem, ISubtitleEncoder subtitleEncoder) + public EncodingHelper(IMediaEncoder mediaEncoder, IFileSystem fileSystem, ISubtitleEncoder subtitleEncoder) { _mediaEncoder = mediaEncoder; - _config = config; _fileSystem = fileSystem; _subtitleEncoder = subtitleEncoder; } @@ -151,10 +150,13 @@ namespace MediaBrowser.Controller.MediaEncoding public string GetInputFormat(string container) { - if (string.Equals(container, "mkv", StringComparison.OrdinalIgnoreCase)) + if (string.IsNullOrWhiteSpace(container)) { - return "matroska"; + return null; } + + container = container.Replace("mkv", "matroska", StringComparison.OrdinalIgnoreCase); + if (string.Equals(container, "ts", StringComparison.OrdinalIgnoreCase)) { return "mpegts"; @@ -205,6 +207,14 @@ namespace MediaBrowser.Controller.MediaEncoding { return null; } + if (string.Equals(container, "rmvb", StringComparison.OrdinalIgnoreCase)) + { + return null; + } + if (string.Equals(container, "rtp", StringComparison.OrdinalIgnoreCase)) + { + return null; + } // Seeing reported failures here, not sure yet if this is related to specfying input format if (string.Equals(container, "m4v", StringComparison.OrdinalIgnoreCase)) @@ -919,19 +929,6 @@ namespace MediaBrowser.Controller.MediaEncoding return false; } - // Video bitrate must fall within requested value - if (request.AudioBitRate.HasValue) - { - if (!audioStream.BitRate.HasValue || audioStream.BitRate.Value <= 0) - { - return false; - } - if (audioStream.BitRate.Value > request.AudioBitRate.Value) - { - return false; - } - } - // Channels must fall within requested value var channels = request.AudioChannels ?? request.MaxAudioChannels; if (channels.HasValue) @@ -959,6 +956,19 @@ namespace MediaBrowser.Controller.MediaEncoding } } + // Video bitrate must fall within requested value + if (request.AudioBitRate.HasValue) + { + if (!audioStream.BitRate.HasValue || audioStream.BitRate.Value <= 0) + { + return false; + } + if (audioStream.BitRate.Value > request.AudioBitRate.Value) + { + return false; + } + } + return request.EnableAutoStreamCopy; } @@ -1616,26 +1626,6 @@ namespace MediaBrowser.Controller.MediaEncoding inputModifier += " -f " + inputFormat; } } - - // Only do this for video files due to sometimes unpredictable codec names coming from BDInfo - if (state.VideoType == VideoType.VideoFile && state.RunTimeTicks.HasValue && string.IsNullOrWhiteSpace(encodingOptions.HardwareAccelerationType)) - { - foreach (var stream in state.MediaSource.MediaStreams) - { - if (!stream.IsExternal && stream.Type != MediaStreamType.Subtitle) - { - if (!string.IsNullOrWhiteSpace(stream.Codec) && stream.Index != -1) - { - var decoder = GetDecoderFromCodec(stream.Codec); - - if (!string.IsNullOrWhiteSpace(decoder)) - { - inputModifier += " -codec:" + stream.Index.ToString(_usCulture) + " " + decoder; - } - } - } - } - } } if (state.MediaSource.RequiresLooping) @@ -1666,14 +1656,33 @@ namespace MediaBrowser.Controller.MediaEncoding state.RunTimeTicks = mediaSource.RunTimeTicks; state.RemoteHttpHeaders = mediaSource.RequiredHttpHeaders; + state.IsoType = mediaSource.IsoType; + if (mediaSource.VideoType.HasValue) { state.VideoType = mediaSource.VideoType.Value; - } - state.IsoType = mediaSource.IsoType; - - state.PlayableStreamFileNames = mediaSource.PlayableStreamFileNames.ToList(); + if (mediaSource.VideoType.Value == VideoType.BluRay || mediaSource.VideoType.Value == VideoType.Dvd) + { + state.PlayableStreamFileNames = Video.QueryPlayableStreamFiles(state.MediaPath, mediaSource.VideoType.Value); + } + else if (mediaSource.VideoType.Value == VideoType.Iso && state.IsoType == IsoType.BluRay) + { + state.PlayableStreamFileNames = Video.QueryPlayableStreamFiles(state.MediaPath, VideoType.BluRay); + } + else if (mediaSource.VideoType.Value == VideoType.Iso && state.IsoType == IsoType.Dvd) + { + state.PlayableStreamFileNames = Video.QueryPlayableStreamFiles(state.MediaPath, VideoType.Dvd); + } + else + { + state.PlayableStreamFileNames = new List<string>(); + } + } + else + { + state.PlayableStreamFileNames = new List<string>(); + } if (mediaSource.Timestamp.HasValue) { @@ -1693,7 +1702,8 @@ namespace MediaBrowser.Controller.MediaEncoding state.InputAudioSync = "1"; } - if (string.Equals(mediaSource.Container, "wma", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(mediaSource.Container, "wma", StringComparison.OrdinalIgnoreCase) || + string.Equals(mediaSource.Container, "asf", StringComparison.OrdinalIgnoreCase)) { // Seeing some stuttering when transcoding wma to audio-only HLS state.InputAudioSync = "1"; @@ -1767,50 +1777,54 @@ namespace MediaBrowser.Controller.MediaEncoding return null; } + return GetVideoDecoder(state.MediaSource.VideoType ?? VideoType.VideoFile, state.VideoStream, encodingOptions); + } + + public string GetVideoDecoder(VideoType videoType, MediaStream videoStream, EncodingOptions encodingOptions) + { // Only use alternative encoders for video files. // When using concat with folder rips, if the mfx session fails to initialize, ffmpeg will be stuck retrying and will not exit gracefully // Since transcoding of folder rips is expiremental anyway, it's not worth adding additional variables such as this. - if (state.VideoType != VideoType.VideoFile) + if (videoType != VideoType.VideoFile) { return null; } - if (state.VideoStream != null && - !string.IsNullOrWhiteSpace(state.VideoStream.Codec) && - !string.IsNullOrWhiteSpace(encodingOptions.HardwareAccelerationType) && - encodingOptions.EnableHardwareDecoding) + if (videoStream != null && + !string.IsNullOrWhiteSpace(videoStream.Codec) && + !string.IsNullOrWhiteSpace(encodingOptions.HardwareAccelerationType)) { if (string.Equals(encodingOptions.HardwareAccelerationType, "qsv", StringComparison.OrdinalIgnoreCase)) { - switch (state.MediaSource.VideoStream.Codec.ToLower()) + switch (videoStream.Codec.ToLower()) { case "avc": case "h264": - if (_mediaEncoder.SupportsDecoder("h264_qsv")) + if (_mediaEncoder.SupportsDecoder("h264_qsv") && encodingOptions.HardwareDecodingCodecs.Contains("h264", StringComparer.OrdinalIgnoreCase)) { // qsv decoder does not support 10-bit input - if ((state.VideoStream.BitDepth ?? 8) > 8) + if ((videoStream.BitDepth ?? 8) > 8) { return null; } return "-c:v h264_qsv "; } break; - //case "hevc": - //case "h265": - // if (_mediaEncoder.SupportsDecoder("hevc_qsv")) - // { - // return "-c:v hevc_qsv "; - // } - // break; + case "hevc": + case "h265": + if (_mediaEncoder.SupportsDecoder("hevc_qsv") && encodingOptions.HardwareDecodingCodecs.Contains("hevc", StringComparer.OrdinalIgnoreCase)) + { + return "-c:v hevc_qsv "; + } + break; case "mpeg2video": - if (_mediaEncoder.SupportsDecoder("mpeg2_qsv")) + if (_mediaEncoder.SupportsDecoder("mpeg2_qsv") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg2video", StringComparer.OrdinalIgnoreCase)) { return "-c:v mpeg2_qsv "; } break; case "vc1": - if (_mediaEncoder.SupportsDecoder("vc1_qsv")) + if (_mediaEncoder.SupportsDecoder("vc1_qsv") && encodingOptions.HardwareDecodingCodecs.Contains("vc1", StringComparer.OrdinalIgnoreCase)) { return "-c:v vc1_qsv "; } @@ -1820,22 +1834,40 @@ namespace MediaBrowser.Controller.MediaEncoding else if (string.Equals(encodingOptions.HardwareAccelerationType, "nvenc", StringComparison.OrdinalIgnoreCase)) { - switch (state.MediaSource.VideoStream.Codec.ToLower()) + switch (videoStream.Codec.ToLower()) { case "avc": case "h264": - if (_mediaEncoder.SupportsDecoder("h264_cuvid")) + if (_mediaEncoder.SupportsDecoder("h264_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("h264", StringComparer.OrdinalIgnoreCase)) { return "-c:v h264_cuvid "; } break; case "hevc": case "h265": - if (_mediaEncoder.SupportsDecoder("hevc_cuvid")) + if (_mediaEncoder.SupportsDecoder("hevc_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("hevc", StringComparer.OrdinalIgnoreCase)) { return "-c:v hevc_cuvid "; } break; + case "mpeg2video": + if (_mediaEncoder.SupportsDecoder("mpeg2_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg2video", StringComparer.OrdinalIgnoreCase)) + { + return "-c:v mpeg2_cuvid "; + } + break; + case "vc1": + if (_mediaEncoder.SupportsDecoder("vc1_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("vc1", StringComparer.OrdinalIgnoreCase)) + { + return "-c:v vc1_cuvid "; + } + break; + case "mpeg4": + if (_mediaEncoder.SupportsDecoder("mpeg4_cuvid") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg4", StringComparer.OrdinalIgnoreCase)) + { + return "-c:v mpeg4_cuvid "; + } + break; } } } @@ -2100,6 +2132,7 @@ namespace MediaBrowser.Controller.MediaEncoding var vn = string.Empty; var hasArt = !string.IsNullOrWhiteSpace(state.AlbumCoverPath); + hasArt = false; if (hasArt) { diff --git a/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs b/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs index 8683a6af4..81269fe3f 100644 --- a/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs +++ b/MediaBrowser.Controller/MediaEncoding/IEncodingManager.cs @@ -1,5 +1,8 @@ -using System.Threading; +using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.MediaEncoding { @@ -8,9 +11,6 @@ namespace MediaBrowser.Controller.MediaEncoding /// <summary> /// Refreshes the chapter images. /// </summary> - /// <param name="options">The options.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task{System.Boolean}.</returns> - Task<bool> RefreshChapterImages(ChapterImageRefreshOptions options, CancellationToken cancellationToken); + Task<bool> RefreshChapterImages(Video video, List<ChapterInfo> chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs index 10d7b9a7e..05bb35771 100644 --- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs +++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs @@ -39,29 +39,16 @@ namespace MediaBrowser.Controller.MediaEncoding /// <summary> /// Extracts the video image. /// </summary> - /// <param name="inputFiles">The input files.</param> - /// <param name="protocol">The protocol.</param> - /// <param name="threedFormat">The threed format.</param> - /// <param name="offset">The offset.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task{Stream}.</returns> - Task<string> ExtractVideoImage(string[] inputFiles, string container, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken); + Task<string> ExtractVideoImage(string[] inputFiles, string container, MediaProtocol protocol, MediaStream videoStream, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken); - Task<string> ExtractVideoImage(string[] inputFiles, string container, MediaProtocol protocol, int? imageStreamIndex, CancellationToken cancellationToken); + Task<string> ExtractVideoImage(string[] inputFiles, string container, MediaProtocol protocol, MediaStream imageStream, int? imageStreamIndex, CancellationToken cancellationToken); /// <summary> /// Extracts the video images on interval. /// </summary> - /// <param name="inputFiles">The input files.</param> - /// <param name="protocol">The protocol.</param> - /// <param name="threedFormat">The threed format.</param> - /// <param name="interval">The interval.</param> - /// <param name="targetDirectory">The target directory.</param> - /// <param name="filenamePrefix">The filename prefix.</param> - /// <param name="maxWidth">The maximum width.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> Task ExtractVideoImagesOnInterval(string[] inputFiles, + string container, + MediaStream videoStream, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan interval, diff --git a/MediaBrowser.Controller/MediaEncoding/JobLogger.cs b/MediaBrowser.Controller/MediaEncoding/JobLogger.cs deleted file mode 100644 index 03e4f7771..000000000 --- a/MediaBrowser.Controller/MediaEncoding/JobLogger.cs +++ /dev/null @@ -1,149 +0,0 @@ -using MediaBrowser.Model.Extensions; -using MediaBrowser.Model.Logging; -using System; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; - -namespace MediaBrowser.Controller.MediaEncoding -{ - public class JobLogger - { - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - private readonly ILogger _logger; - - public JobLogger(ILogger logger) - { - _logger = logger; - } - - public async void StartStreamingLog(EncodingJobInfo state, Stream source, Stream target) - { - try - { - using (var reader = new StreamReader(source)) - { - while (!reader.EndOfStream) - { - var line = await reader.ReadLineAsync().ConfigureAwait(false); - - ParseLogLine(line, state); - - var bytes = Encoding.UTF8.GetBytes(Environment.NewLine + line); - - await target.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); - await target.FlushAsync().ConfigureAwait(false); - } - } - } - catch (ObjectDisposedException) - { - // Don't spam the log. This doesn't seem to throw in windows, but sometimes under linux - } - catch (Exception ex) - { - _logger.ErrorException("Error reading ffmpeg log", ex); - } - } - - private void ParseLogLine(string line, EncodingJobInfo state) - { - float? framerate = null; - double? percent = null; - TimeSpan? transcodingPosition = null; - long? bytesTranscoded = null; - int? bitRate = null; - - var parts = line.Split(' '); - - var totalMs = state.RunTimeTicks.HasValue - ? TimeSpan.FromTicks(state.RunTimeTicks.Value).TotalMilliseconds - : 0; - - var startMs = state.BaseRequest.StartTimeTicks.HasValue - ? TimeSpan.FromTicks(state.BaseRequest.StartTimeTicks.Value).TotalMilliseconds - : 0; - - for (var i = 0; i < parts.Length; i++) - { - var part = parts[i]; - - if (string.Equals(part, "fps=", StringComparison.OrdinalIgnoreCase) && - (i + 1 < parts.Length)) - { - var rate = parts[i + 1]; - float val; - - if (float.TryParse(rate, NumberStyles.Any, _usCulture, out val)) - { - framerate = val; - } - } - else if (state.RunTimeTicks.HasValue && - part.StartsWith("time=", StringComparison.OrdinalIgnoreCase)) - { - var time = part.Split(new[] { '=' }, 2).Last(); - TimeSpan val; - - if (TimeSpan.TryParse(time, _usCulture, out val)) - { - var currentMs = startMs + val.TotalMilliseconds; - - var percentVal = currentMs / totalMs; - percent = 100 * percentVal; - - transcodingPosition = val; - } - } - else if (part.StartsWith("size=", StringComparison.OrdinalIgnoreCase)) - { - var size = part.Split(new[] { '=' }, 2).Last(); - - int? scale = null; - if (size.IndexOf("kb", StringComparison.OrdinalIgnoreCase) != -1) - { - scale = 1024; - size = size.Replace("kb", string.Empty, StringComparison.OrdinalIgnoreCase); - } - - if (scale.HasValue) - { - long val; - - if (long.TryParse(size, NumberStyles.Any, _usCulture, out val)) - { - bytesTranscoded = val * scale.Value; - } - } - } - else if (part.StartsWith("bitrate=", StringComparison.OrdinalIgnoreCase)) - { - var rate = part.Split(new[] { '=' }, 2).Last(); - - int? scale = null; - if (rate.IndexOf("kbits/s", StringComparison.OrdinalIgnoreCase) != -1) - { - scale = 1024; - rate = rate.Replace("kbits/s", string.Empty, StringComparison.OrdinalIgnoreCase); - } - - if (scale.HasValue) - { - float val; - - if (float.TryParse(rate, NumberStyles.Any, _usCulture, out val)) - { - bitRate = (int)Math.Ceiling(val * scale.Value); - } - } - } - } - - if (framerate.HasValue || percent.HasValue) - { - state.ReportTranscodingProgress(transcodingPosition, framerate, percent, bytesTranscoded, bitRate); - } - } - } -} diff --git a/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs b/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs index b025011d7..81e294069 100644 --- a/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs +++ b/MediaBrowser.Controller/Net/AuthenticatedAttribute.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; using MediaBrowser.Model.Services; namespace MediaBrowser.Controller.Net @@ -53,8 +52,7 @@ namespace MediaBrowser.Controller.Net public IEnumerable<string> GetRoles() { - return (Roles ?? string.Empty).Split(',') - .Where(i => !string.IsNullOrWhiteSpace(i)); + return (Roles ?? string.Empty).Split(new []{ ',' }, StringSplitOptions.RemoveEmptyEntries); } } diff --git a/MediaBrowser.Controller/Persistence/IFileOrganizationRepository.cs b/MediaBrowser.Controller/Persistence/IFileOrganizationRepository.cs deleted file mode 100644 index f71784d82..000000000 --- a/MediaBrowser.Controller/Persistence/IFileOrganizationRepository.cs +++ /dev/null @@ -1,45 +0,0 @@ -using MediaBrowser.Model.FileOrganization; -using MediaBrowser.Model.Querying; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Controller.Persistence -{ - public interface IFileOrganizationRepository - { - /// <summary> - /// Saves the result. - /// </summary> - /// <param name="result">The result.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - Task SaveResult(FileOrganizationResult result, CancellationToken cancellationToken); - - /// <summary> - /// Deletes the specified identifier. - /// </summary> - /// <param name="id">The identifier.</param> - /// <returns>Task.</returns> - Task Delete(string id); - - /// <summary> - /// Gets the result. - /// </summary> - /// <param name="id">The identifier.</param> - /// <returns>FileOrganizationResult.</returns> - FileOrganizationResult GetResult(string id); - - /// <summary> - /// Gets the results. - /// </summary> - /// <param name="query">The query.</param> - /// <returns>IEnumerable{FileOrganizationResult}.</returns> - QueryResult<FileOrganizationResult> GetResults(FileOrganizationResultQuery query); - - /// <summary> - /// Deletes all. - /// </summary> - /// <returns>Task.</returns> - Task DeleteAll(); - } -} diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs index 58ae1f3b0..bf54914b1 100644 --- a/MediaBrowser.Controller/Persistence/IItemRepository.cs +++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs @@ -35,7 +35,7 @@ namespace MediaBrowser.Controller.Persistence /// </summary> /// <param name="itemId">The item id.</param> /// <returns>Task{IEnumerable{ItemReview}}.</returns> - IEnumerable<ItemReview> GetCriticReviews(Guid itemId); + List<ItemReview> GetCriticReviews(Guid itemId); /// <summary> /// Saves the critic reviews. @@ -65,7 +65,7 @@ namespace MediaBrowser.Controller.Persistence /// </summary> /// <param name="id"></param> /// <returns></returns> - IEnumerable<ChapterInfo> GetChapters(Guid id); + List<ChapterInfo> GetChapters(Guid id); /// <summary> /// Gets a single chapter for an item @@ -78,18 +78,14 @@ namespace MediaBrowser.Controller.Persistence /// <summary> /// Saves the chapters. /// </summary> - /// <param name="id">The id.</param> - /// <param name="chapters">The chapters.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - Task SaveChapters(Guid id, List<ChapterInfo> chapters, CancellationToken cancellationToken); + Task SaveChapters(Guid id, List<ChapterInfo> chapters); /// <summary> /// Gets the media streams. /// </summary> /// <param name="query">The query.</param> /// <returns>IEnumerable{MediaStream}.</returns> - IEnumerable<MediaStream> GetMediaStreams(MediaStreamQuery query); + List<MediaStream> GetMediaStreams(MediaStreamQuery query); /// <summary> /// Saves the media streams. diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs index c992ac56a..aec0668d4 100644 --- a/MediaBrowser.Controller/Playlists/Playlist.cs +++ b/MediaBrowser.Controller/Playlists/Playlist.cs @@ -105,7 +105,7 @@ namespace MediaBrowser.Controller.Playlists if (query != null) { - items = items.Where(i => UserViewBuilder.FilterItem(i, query)); + items = items.Where(i => UserViewBuilder.FilterItem(i, query)).ToList(); } return items; @@ -116,12 +116,12 @@ namespace MediaBrowser.Controller.Playlists return GetLinkedChildrenInfos(); } - private IEnumerable<BaseItem> GetPlayableItems(User user, DtoOptions options) + private List<BaseItem> GetPlayableItems(User user, DtoOptions options) { return GetPlaylistItems(MediaType, base.GetChildren(user, true), user, options); } - public static IEnumerable<BaseItem> GetPlaylistItems(string playlistMediaType, IEnumerable<BaseItem> inputItems, User user, DtoOptions options) + public static List<BaseItem> GetPlaylistItems(string playlistMediaType, IEnumerable<BaseItem> inputItems, User user, DtoOptions options) { if (user != null) { @@ -182,10 +182,7 @@ namespace MediaBrowser.Controller.Playlists DtoOptions = options }; - var itemsResult = folder.GetItems(query); - var items = itemsResult.Items; - - return items; + return folder.GetItemList(query); } return new[] { item }; diff --git a/MediaBrowser.Controller/Providers/AlbumInfo.cs b/MediaBrowser.Controller/Providers/AlbumInfo.cs index b88477409..74feb4ea2 100644 --- a/MediaBrowser.Controller/Providers/AlbumInfo.cs +++ b/MediaBrowser.Controller/Providers/AlbumInfo.cs @@ -9,7 +9,7 @@ namespace MediaBrowser.Controller.Providers /// Gets or sets the album artist. /// </summary> /// <value>The album artist.</value> - public List<string> AlbumArtists { get; set; } + public string[] AlbumArtists { get; set; } /// <summary> /// Gets or sets the artist provider ids. @@ -22,7 +22,7 @@ namespace MediaBrowser.Controller.Providers { ArtistProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); SongInfos = new List<SongInfo>(); - AlbumArtists = new List<string>(); + AlbumArtists = EmptyStringArray; } } }
\ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/DirectoryService.cs b/MediaBrowser.Controller/Providers/DirectoryService.cs index 6d220f3a3..337bb23a4 100644 --- a/MediaBrowser.Controller/Providers/DirectoryService.cs +++ b/MediaBrowser.Controller/Providers/DirectoryService.cs @@ -13,10 +13,10 @@ namespace MediaBrowser.Controller.Providers public class DirectoryService : IDirectoryService { private readonly ILogger _logger; - private readonly IFileSystem _fileSystem; + private readonly IFileSystem _fileSystem; - private readonly ConcurrentDictionary<string, Dictionary<string, FileSystemMetadata>> _cache = - new ConcurrentDictionary<string, Dictionary<string, FileSystemMetadata>>(StringComparer.OrdinalIgnoreCase); + private readonly ConcurrentDictionary<string, FileSystemMetadata[]> _cache = + new ConcurrentDictionary<string, FileSystemMetadata[]>(StringComparer.OrdinalIgnoreCase); private readonly ConcurrentDictionary<string, FileSystemMetadata> _fileCache = new ConcurrentDictionary<string, FileSystemMetadata>(StringComparer.OrdinalIgnoreCase); @@ -24,7 +24,7 @@ namespace MediaBrowser.Controller.Providers public DirectoryService(ILogger logger, IFileSystem fileSystem) { _logger = logger; - _fileSystem = fileSystem; + _fileSystem = fileSystem; } public DirectoryService(IFileSystem fileSystem) @@ -32,28 +32,23 @@ namespace MediaBrowser.Controller.Providers { } - public IEnumerable<FileSystemMetadata> GetFileSystemEntries(string path) + public FileSystemMetadata[] GetFileSystemEntries(string path) { return GetFileSystemEntries(path, false); } - public Dictionary<string, FileSystemMetadata> GetFileSystemDictionary(string path) - { - return GetFileSystemDictionary(path, false); - } - - private Dictionary<string, FileSystemMetadata> GetFileSystemDictionary(string path, bool clearCache) + private FileSystemMetadata[] GetFileSystemEntries(string path, bool clearCache) { if (string.IsNullOrWhiteSpace(path)) { throw new ArgumentNullException("path"); } - Dictionary<string, FileSystemMetadata> entries; + FileSystemMetadata[] entries; if (clearCache) { - Dictionary<string, FileSystemMetadata> removed; + FileSystemMetadata[] removed; _cache.TryRemove(path, out removed); } @@ -62,37 +57,22 @@ namespace MediaBrowser.Controller.Providers { //_logger.Debug("Getting files for " + path); - entries = new Dictionary<string, FileSystemMetadata>(StringComparer.OrdinalIgnoreCase); - try { // using EnumerateFileSystemInfos doesn't handle reparse points (symlinks) - var list = _fileSystem.GetFileSystemEntries(path) - .ToList(); - - // Seeing dupes on some users file system for some reason - foreach (var item in list) - { - entries[item.FullName] = item; - } + entries = _fileSystem.GetFileSystemEntries(path).ToArray(); } catch (IOException) { + entries = new FileSystemMetadata[] { }; } - //var group = entries.ToLookup(i => _fileSystem.GetDirectoryName(i.FullName)).ToList(); - _cache.TryAdd(path, entries); } return entries; } - private IEnumerable<FileSystemMetadata> GetFileSystemEntries(string path, bool clearCache) - { - return GetFileSystemDictionary(path, clearCache).Values; - } - public IEnumerable<FileSystemMetadata> GetFiles(string path) { return GetFiles(path, false); @@ -103,16 +83,6 @@ namespace MediaBrowser.Controller.Providers return GetFileSystemEntries(path, clearCache).Where(i => !i.IsDirectory); } - public IEnumerable<string> GetFilePaths(string path) - { - return _fileSystem.GetFilePaths(path); - } - - public IEnumerable<string> GetFilePaths(string path, bool clearCache) - { - return _fileSystem.GetFilePaths(path); - } - public FileSystemMetadata GetFile(string path) { FileSystemMetadata file; @@ -133,10 +103,5 @@ namespace MediaBrowser.Controller.Providers return file; //return _fileSystem.GetFileInfo(path); } - - public IEnumerable<FileSystemMetadata> GetDirectories(string path) - { - return GetFileSystemEntries(path, false).Where(i => i.IsDirectory); - } } } diff --git a/MediaBrowser.Controller/Providers/EpisodeInfo.cs b/MediaBrowser.Controller/Providers/EpisodeInfo.cs index b8e88ea53..5df999ab0 100644 --- a/MediaBrowser.Controller/Providers/EpisodeInfo.cs +++ b/MediaBrowser.Controller/Providers/EpisodeInfo.cs @@ -10,7 +10,6 @@ namespace MediaBrowser.Controller.Providers public int? IndexNumberEnd { get; set; } public bool IsMissingEpisode { get; set; } - public bool IsVirtualUnaired { get; set; } public EpisodeInfo() { diff --git a/MediaBrowser.Controller/Providers/IDirectoryService.cs b/MediaBrowser.Controller/Providers/IDirectoryService.cs index 1b203f32c..374703948 100644 --- a/MediaBrowser.Controller/Providers/IDirectoryService.cs +++ b/MediaBrowser.Controller/Providers/IDirectoryService.cs @@ -1,18 +1,12 @@ using System.Collections.Generic; - -using MediaBrowser.Controller.IO; using MediaBrowser.Model.IO; namespace MediaBrowser.Controller.Providers { public interface IDirectoryService { - IEnumerable<FileSystemMetadata> GetFileSystemEntries(string path); - IEnumerable<FileSystemMetadata> GetDirectories(string path); + FileSystemMetadata[] GetFileSystemEntries(string path); IEnumerable<FileSystemMetadata> GetFiles(string path); - IEnumerable<string> GetFilePaths(string path); - IEnumerable<string> GetFilePaths(string path, bool clearCache); FileSystemMetadata GetFile(string path); - Dictionary<string, FileSystemMetadata> GetFileSystemDictionary(string path); } }
\ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/IDynamicImageProvider.cs b/MediaBrowser.Controller/Providers/IDynamicImageProvider.cs index 9c3f94763..e96a2d65e 100644 --- a/MediaBrowser.Controller/Providers/IDynamicImageProvider.cs +++ b/MediaBrowser.Controller/Providers/IDynamicImageProvider.cs @@ -13,7 +13,7 @@ namespace MediaBrowser.Controller.Providers /// </summary> /// <param name="item">The item.</param> /// <returns>IEnumerable{ImageType}.</returns> - IEnumerable<ImageType> GetSupportedImages(IHasImages item); + IEnumerable<ImageType> GetSupportedImages(IHasMetadata item); /// <summary> /// Gets the image. @@ -22,6 +22,6 @@ namespace MediaBrowser.Controller.Providers /// <param name="type">The type.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task{DynamicImageResponse}.</returns> - Task<DynamicImageResponse> GetImage(IHasImages item, ImageType type, CancellationToken cancellationToken); + Task<DynamicImageResponse> GetImage(IHasMetadata item, ImageType type, CancellationToken cancellationToken); } }
\ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/IImageEnhancer.cs b/MediaBrowser.Controller/Providers/IImageEnhancer.cs index a43941607..a993f536d 100644 --- a/MediaBrowser.Controller/Providers/IImageEnhancer.cs +++ b/MediaBrowser.Controller/Providers/IImageEnhancer.cs @@ -13,7 +13,7 @@ namespace MediaBrowser.Controller.Providers /// <param name="item">The item.</param> /// <param name="imageType">Type of the image.</param> /// <returns><c>true</c> if this enhancer will enhance the supplied image for the supplied item, <c>false</c> otherwise</returns> - bool Supports(IHasImages item, ImageType imageType); + bool Supports(IHasMetadata item, ImageType imageType); /// <summary> /// Gets the priority or order in which this enhancer should be run. @@ -27,7 +27,7 @@ namespace MediaBrowser.Controller.Providers /// <param name="item">The item.</param> /// <param name="imageType">Type of the image.</param> /// <returns>Cache key relating to the current state of this item and configuration</returns> - string GetConfigurationCacheKey(IHasImages item, ImageType imageType); + string GetConfigurationCacheKey(IHasMetadata item, ImageType imageType); /// <summary> /// Gets the size of the enhanced image. @@ -37,7 +37,7 @@ namespace MediaBrowser.Controller.Providers /// <param name="imageIndex">Index of the image.</param> /// <param name="originalImageSize">Size of the original image.</param> /// <returns>ImageSize.</returns> - ImageSize GetEnhancedImageSize(IHasImages item, ImageType imageType, int imageIndex, ImageSize originalImageSize); + ImageSize GetEnhancedImageSize(IHasMetadata item, ImageType imageType, int imageIndex, ImageSize originalImageSize); /// <summary> /// Enhances the image async. @@ -49,6 +49,6 @@ namespace MediaBrowser.Controller.Providers /// <param name="imageIndex">Index of the image.</param> /// <returns>Task{Image}.</returns> /// <exception cref="System.ArgumentNullException"></exception> - Task EnhanceImageAsync(IHasImages item, string inputFile, string outputFile, ImageType imageType, int imageIndex); + Task EnhanceImageAsync(IHasMetadata item, string inputFile, string outputFile, ImageType imageType, int imageIndex); } }
\ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/IImageProvider.cs b/MediaBrowser.Controller/Providers/IImageProvider.cs index 1e5bdfeaf..2b43c9cb8 100644 --- a/MediaBrowser.Controller/Providers/IImageProvider.cs +++ b/MediaBrowser.Controller/Providers/IImageProvider.cs @@ -18,6 +18,6 @@ namespace MediaBrowser.Controller.Providers /// </summary> /// <param name="item">The item.</param> /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> - bool Supports(IHasImages item); + bool Supports(IHasMetadata item); } } diff --git a/MediaBrowser.Controller/Providers/ILocalImageFileProvider.cs b/MediaBrowser.Controller/Providers/ILocalImageFileProvider.cs index 7e5d82843..e93c73a52 100644 --- a/MediaBrowser.Controller/Providers/ILocalImageFileProvider.cs +++ b/MediaBrowser.Controller/Providers/ILocalImageFileProvider.cs @@ -5,6 +5,6 @@ namespace MediaBrowser.Controller.Providers { public interface ILocalImageFileProvider : ILocalImageProvider { - List<LocalImageInfo> GetImages(IHasImages item, IDirectoryService directoryService); + List<LocalImageInfo> GetImages(IHasMetadata item, IDirectoryService directoryService); } }
\ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs index 0ba573da8..703666d66 100644 --- a/MediaBrowser.Controller/Providers/IProviderManager.cs +++ b/MediaBrowser.Controller/Providers/IProviderManager.cs @@ -50,7 +50,7 @@ namespace MediaBrowser.Controller.Providers /// <param name="imageIndex">Index of the image.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - Task SaveImage(IHasImages item, string url, ImageType type, int? imageIndex, CancellationToken cancellationToken); + Task SaveImage(IHasMetadata item, string url, ImageType type, int? imageIndex, CancellationToken cancellationToken); /// <summary> /// Saves the image. @@ -62,13 +62,13 @@ namespace MediaBrowser.Controller.Providers /// <param name="imageIndex">Index of the image.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task.</returns> - Task SaveImage(IHasImages item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken); + Task SaveImage(IHasMetadata item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken); /// <summary> /// Saves the image. /// </summary> /// <returns>Task.</returns> - Task SaveImage(IHasImages item, string source, string mimeType, ImageType type, int? imageIndex, bool? saveLocallyWithMedia, CancellationToken cancellationToken); + Task SaveImage(IHasMetadata item, string source, string mimeType, ImageType type, int? imageIndex, bool? saveLocallyWithMedia, CancellationToken cancellationToken); /// <summary> /// Adds the metadata providers. @@ -84,14 +84,14 @@ namespace MediaBrowser.Controller.Providers /// <param name="query">The query.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task{IEnumerable{RemoteImageInfo}}.</returns> - Task<IEnumerable<RemoteImageInfo>> GetAvailableRemoteImages(IHasImages item, RemoteImageQuery query, CancellationToken cancellationToken); + Task<IEnumerable<RemoteImageInfo>> GetAvailableRemoteImages(IHasMetadata item, RemoteImageQuery query, CancellationToken cancellationToken); /// <summary> /// Gets the image providers. /// </summary> /// <param name="item">The item.</param> /// <returns>IEnumerable{ImageProviderInfo}.</returns> - IEnumerable<ImageProviderInfo> GetRemoteImageProviderInfo(IHasImages item); + IEnumerable<ImageProviderInfo> GetRemoteImageProviderInfo(IHasMetadata item); /// <summary> /// Gets all metadata plugins. @@ -135,7 +135,7 @@ namespace MediaBrowser.Controller.Providers /// </summary> /// <param name="item">The item.</param> /// <returns>MetadataOptions.</returns> - MetadataOptions GetMetadataOptions(IHasImages item); + MetadataOptions GetMetadataOptions(IHasMetadata item); /// <summary> /// Gets the remote search results. diff --git a/MediaBrowser.Controller/Providers/IRemoteImageProvider.cs b/MediaBrowser.Controller/Providers/IRemoteImageProvider.cs index 6b94547bb..86a7939e6 100644 --- a/MediaBrowser.Controller/Providers/IRemoteImageProvider.cs +++ b/MediaBrowser.Controller/Providers/IRemoteImageProvider.cs @@ -18,7 +18,7 @@ namespace MediaBrowser.Controller.Providers /// </summary> /// <param name="item">The item.</param> /// <returns>IEnumerable{ImageType}.</returns> - IEnumerable<ImageType> GetSupportedImages(IHasImages item); + IEnumerable<ImageType> GetSupportedImages(IHasMetadata item); /// <summary> /// Gets the images. @@ -26,7 +26,7 @@ namespace MediaBrowser.Controller.Providers /// <param name="item">The item.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>Task{IEnumerable{RemoteImageInfo}}.</returns> - Task<IEnumerable<RemoteImageInfo>> GetImages(IHasImages item, CancellationToken cancellationToken); + Task<IEnumerable<RemoteImageInfo>> GetImages(IHasMetadata item, CancellationToken cancellationToken); /// <summary> /// Gets the image response. diff --git a/MediaBrowser.Controller/Providers/ItemInfo.cs b/MediaBrowser.Controller/Providers/ItemInfo.cs index 8de11b743..63cc48058 100644 --- a/MediaBrowser.Controller/Providers/ItemInfo.cs +++ b/MediaBrowser.Controller/Providers/ItemInfo.cs @@ -10,7 +10,7 @@ namespace MediaBrowser.Controller.Providers { Path = item.Path; ContainingFolderPath = item.ContainingFolderPath; - IsInMixedFolder = item.DetectIsInMixedFolder(); + IsInMixedFolder = item.IsInMixedFolder; var video = item as Video; if (video != null) diff --git a/MediaBrowser.Controller/Providers/ItemLookupInfo.cs b/MediaBrowser.Controller/Providers/ItemLookupInfo.cs index dc7a04135..98122e776 100644 --- a/MediaBrowser.Controller/Providers/ItemLookupInfo.cs +++ b/MediaBrowser.Controller/Providers/ItemLookupInfo.cs @@ -6,6 +6,8 @@ namespace MediaBrowser.Controller.Providers { public class ItemLookupInfo : IHasProviderIds { + protected static string[] EmptyStringArray = new string[] { }; + /// <summary> /// Gets or sets the name. /// </summary> diff --git a/MediaBrowser.Controller/Providers/SongInfo.cs b/MediaBrowser.Controller/Providers/SongInfo.cs index b83912a00..988e931cd 100644 --- a/MediaBrowser.Controller/Providers/SongInfo.cs +++ b/MediaBrowser.Controller/Providers/SongInfo.cs @@ -4,14 +4,14 @@ namespace MediaBrowser.Controller.Providers { public class SongInfo : ItemLookupInfo { - public List<string> AlbumArtists { get; set; } + public string[] AlbumArtists { get; set; } public string Album { get; set; } public List<string> Artists { get; set; } public SongInfo() { Artists = new List<string>(); - AlbumArtists = new List<string>(); + AlbumArtists = EmptyStringArray; } } }
\ No newline at end of file diff --git a/MediaBrowser.Controller/Sync/ISyncManager.cs b/MediaBrowser.Controller/Sync/ISyncManager.cs index 291632ea5..66f64464f 100644 --- a/MediaBrowser.Controller/Sync/ISyncManager.cs +++ b/MediaBrowser.Controller/Sync/ISyncManager.cs @@ -16,6 +16,7 @@ namespace MediaBrowser.Controller.Sync event EventHandler<GenericEventArgs<SyncJob>> SyncJobUpdated; event EventHandler<GenericEventArgs<SyncJobItem>> SyncJobItemUpdated; event EventHandler<GenericEventArgs<SyncJobItem>> SyncJobItemCreated; + event EventHandler<GenericEventArgs<SyncJobItem>> SyncJobItemCancelled; /// <summary> /// Creates the job. @@ -135,20 +136,6 @@ namespace MediaBrowser.Controller.Sync Task<SyncDataResponse> SyncData(SyncDataRequest request); /// <summary> - /// Marks the job item for removal. - /// </summary> - /// <param name="id">The identifier.</param> - /// <returns>Task.</returns> - Task MarkJobItemForRemoval(string id); - - /// <summary> - /// Unmarks the job item for removal. - /// </summary> - /// <param name="id">The identifier.</param> - /// <returns>Task.</returns> - Task UnmarkJobItemForRemoval(string id); - - /// <summary> /// Gets the library item ids. /// </summary> /// <param name="query">The query.</param> diff --git a/MediaBrowser.Controller/Sync/ISyncRepository.cs b/MediaBrowser.Controller/Sync/ISyncRepository.cs deleted file mode 100644 index 8e9b2bf77..000000000 --- a/MediaBrowser.Controller/Sync/ISyncRepository.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System.Collections.Generic; -using MediaBrowser.Model.Querying; -using MediaBrowser.Model.Sync; -using System.Threading.Tasks; - -namespace MediaBrowser.Controller.Sync -{ - public interface ISyncRepository - { - /// <summary> - /// Gets the job. - /// </summary> - /// <param name="id">The identifier.</param> - /// <returns>SyncJob.</returns> - SyncJob GetJob(string id); - - /// <summary> - /// Creates the specified job. - /// </summary> - /// <param name="job">The job.</param> - /// <returns>Task.</returns> - Task Create(SyncJob job); - - /// <summary> - /// Updates the specified job. - /// </summary> - /// <param name="job">The job.</param> - /// <returns>Task.</returns> - Task Update(SyncJob job); - - /// <summary> - /// Deletes the job. - /// </summary> - /// <param name="id">The identifier.</param> - /// <returns>Task.</returns> - Task DeleteJob(string id); - - /// <summary> - /// Gets the jobs. - /// </summary> - /// <param name="query">The query.</param> - /// <returns>QueryResult<SyncJob>.</returns> - QueryResult<SyncJob> GetJobs(SyncJobQuery query); - - /// <summary> - /// Gets the job item. - /// </summary> - /// <param name="id">The identifier.</param> - /// <returns>SyncJobItem.</returns> - SyncJobItem GetJobItem(string id); - - /// <summary> - /// Creates the specified job item. - /// </summary> - /// <param name="jobItem">The job item.</param> - /// <returns>Task.</returns> - Task Create(SyncJobItem jobItem); - - /// <summary> - /// Updates the specified job item. - /// </summary> - /// <param name="jobItem">The job item.</param> - /// <returns>Task.</returns> - Task Update(SyncJobItem jobItem); - - /// <summary> - /// Gets the job items. - /// </summary> - /// <param name="query">The query.</param> - /// <returns>IEnumerable<SyncJobItem>.</returns> - QueryResult<SyncJobItem> GetJobItems(SyncJobItemQuery query); - - /// <summary> - /// Gets the library item ids. - /// </summary> - /// <param name="query">The query.</param> - /// <returns>QueryResult<System.String>.</returns> - Dictionary<string, SyncedItemProgress> GetSyncedItemProgresses(SyncJobItemQuery query); - } -} |
