diff --git a/MediaBrowser.Api/ItemRefreshService.cs b/MediaBrowser.Api/ItemRefreshService.cs index 78bc14ab0..6a7b4826c 100644 --- a/MediaBrowser.Api/ItemRefreshService.cs +++ b/MediaBrowser.Api/ItemRefreshService.cs @@ -53,7 +53,7 @@ namespace MediaBrowser.Api var albums = _libraryManager.RootFolder .GetRecursiveChildren() .OfType() - .Where(i => i.HasArtist(item.Name)) + .Where(i => i.HasAnyArtist(item.Name)) .ToList(); var musicArtists = albums diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs index 6517d738b..86689f5cf 100644 --- a/MediaBrowser.Api/ItemUpdateService.cs +++ b/MediaBrowser.Api/ItemUpdateService.cs @@ -389,20 +389,33 @@ namespace MediaBrowser.Api game.PlayersSupported = request.Players; } - var song = item as Audio; + var hasAlbumArtists = item as IHasAlbumArtist; + if (hasAlbumArtists != null) + { + hasAlbumArtists.AlbumArtists = request + .AlbumArtists + .Select(i => i.Name) + .ToList(); + } + var hasArtists = item as IHasArtist; + if (hasArtists != null) + { + hasArtists.Artists = request + .ArtistItems + .Select(i => i.Name) + .ToList(); + } + + var song = item as Audio; if (song != null) { song.Album = request.Album; - song.AlbumArtists = string.IsNullOrWhiteSpace(request.AlbumArtist) ? new List() : new List { request.AlbumArtist }; - song.Artists = request.Artists.ToList(); } var musicVideo = item as MusicVideo; - if (musicVideo != null) { - musicVideo.Artists = request.Artists.ToList(); musicVideo.Album = request.Album; } diff --git a/MediaBrowser.Api/Music/AlbumsService.cs b/MediaBrowser.Api/Music/AlbumsService.cs index 76c6c5776..a1c98addb 100644 --- a/MediaBrowser.Api/Music/AlbumsService.cs +++ b/MediaBrowser.Api/Music/AlbumsService.cs @@ -77,15 +77,13 @@ namespace MediaBrowser.Api.Music var album1 = (MusicAlbum)item1; var album2 = (MusicAlbum)item2; - var artists1 = album1.GetRecursiveChildren(i => i is IHasArtist) - .Cast() - .SelectMany(i => i.AllArtists) + var artists1 = album1 + .AllArtists .Distinct(StringComparer.OrdinalIgnoreCase) .ToList(); - var artists2 = album2.GetRecursiveChildren(i => i is IHasArtist) - .Cast() - .SelectMany(i => i.AllArtists) + var artists2 = album2 + .AllArtists .Distinct(StringComparer.OrdinalIgnoreCase) .ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); diff --git a/MediaBrowser.Api/Playback/TranscodingThrottler.cs b/MediaBrowser.Api/Playback/TranscodingThrottler.cs index f22ef4326..c486a44ea 100644 --- a/MediaBrowser.Api/Playback/TranscodingThrottler.cs +++ b/MediaBrowser.Api/Playback/TranscodingThrottler.cs @@ -25,10 +25,7 @@ namespace MediaBrowser.Api.Playback public void Start() { - if (_processManager.SupportsSuspension) - { - //_timer = new Timer(TimerCallback, null, 5000, 5000); - } + _timer = new Timer(TimerCallback, null, 5000, 5000); } private void TimerCallback(object state) @@ -58,8 +55,7 @@ namespace MediaBrowser.Api.Playback try { - //_job.Process.StandardInput.WriteLine("p"); - _processManager.SuspendProcess(_job.Process); + _job.Process.StandardInput.WriteLine("p"); _isPaused = true; } catch (Exception ex) @@ -77,8 +73,7 @@ namespace MediaBrowser.Api.Playback try { - //_job.Process.StandardInput.WriteLine("u"); - _processManager.ResumeProcess(_job.Process); + _job.Process.StandardInput.WriteLine("u"); _isPaused = false; } catch (Exception ex) diff --git a/MediaBrowser.Api/SearchService.cs b/MediaBrowser.Api/SearchService.cs index ee48946d5..2cca72593 100644 --- a/MediaBrowser.Api/SearchService.cs +++ b/MediaBrowser.Api/SearchService.cs @@ -211,7 +211,7 @@ namespace MediaBrowser.Api result.SongCount = album.Tracks.Count(); result.Artists = album.Artists.ToArray(); - result.AlbumArtist = album.AlbumArtists.FirstOrDefault(); + result.AlbumArtist = album.AlbumArtist; } var song = item as Audio; diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs index bf5c04540..4655f2c6f 100644 --- a/MediaBrowser.Api/StartupWizardService.cs +++ b/MediaBrowser.Api/StartupWizardService.cs @@ -65,6 +65,7 @@ namespace MediaBrowser.Api _config.Configuration.MergeMetadataAndImagesByName = true; _config.Configuration.EnableStandaloneMetadata = true; _config.Configuration.EnableLibraryMetadataSubFolder = true; + _config.Configuration.EnableUserSpecificUserViews = true; _config.SaveConfiguration(); } diff --git a/MediaBrowser.Api/Subtitles/SubtitleService.cs b/MediaBrowser.Api/Subtitles/SubtitleService.cs index c7997be5b..07eb74e81 100644 --- a/MediaBrowser.Api/Subtitles/SubtitleService.cs +++ b/MediaBrowser.Api/Subtitles/SubtitleService.cs @@ -125,13 +125,15 @@ namespace MediaBrowser.Api.Subtitles private readonly ISubtitleManager _subtitleManager; private readonly ISubtitleEncoder _subtitleEncoder; private readonly IMediaSourceManager _mediaSourceManager; + private readonly IProviderManager _providerManager; - public SubtitleService(ILibraryManager libraryManager, ISubtitleManager subtitleManager, ISubtitleEncoder subtitleEncoder, IMediaSourceManager mediaSourceManager) + public SubtitleService(ILibraryManager libraryManager, ISubtitleManager subtitleManager, ISubtitleEncoder subtitleEncoder, IMediaSourceManager mediaSourceManager, IProviderManager providerManager) { _libraryManager = libraryManager; _subtitleManager = subtitleManager; _subtitleEncoder = subtitleEncoder; _mediaSourceManager = mediaSourceManager; + _providerManager = providerManager; } public object Get(GetSubtitlePlaylist request) @@ -256,7 +258,7 @@ namespace MediaBrowser.Api.Subtitles await _subtitleManager.DownloadSubtitles(video, request.SubtitleId, CancellationToken.None) .ConfigureAwait(false); - await video.RefreshMetadata(new MetadataRefreshOptions(new DirectoryService()), CancellationToken.None).ConfigureAwait(false); + _providerManager.QueueRefresh(video.Id, new MetadataRefreshOptions()); } catch (Exception ex) { diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index 9b5ef3a98..bdaad49e6 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -46,9 +46,6 @@ namespace MediaBrowser.Api.UserLibrary [ApiMember(Name = "PersonTypes", Description = "Optional. If specified, along with Person, results will be filtered to include only those containing the specified person and PersonType. Allows multiple, comma-delimited", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET")] public string PersonTypes { get; set; } - [ApiMember(Name = "AllGenres", Description = "Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] - public string AllGenres { get; set; } - /// /// Limit results to items containing specific studios /// @@ -56,6 +53,9 @@ namespace MediaBrowser.Api.UserLibrary [ApiMember(Name = "Studios", Description = "Optional. If specified, results will be filtered based on studio. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] public string Studios { get; set; } + [ApiMember(Name = "StudioIds", Description = "Optional. If specified, results will be filtered based on studio. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] + public string StudioIds { get; set; } + /// /// Gets or sets the studios. /// @@ -63,6 +63,9 @@ namespace MediaBrowser.Api.UserLibrary [ApiMember(Name = "Artists", Description = "Optional. If specified, results will be filtered based on artist. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] public string Artists { get; set; } + [ApiMember(Name = "ArtistIds", Description = "Optional. If specified, results will be filtered based on artist. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] + public string ArtistIds { get; set; } + [ApiMember(Name = "Albums", Description = "Optional. If specified, results will be filtered based on album. This allows multiple, pipe delimeted.", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "GET", AllowMultiple = true)] public string Albums { get; set; } @@ -226,22 +229,22 @@ namespace MediaBrowser.Api.UserLibrary [ApiMember(Name = "CollapseBoxSetItems", Description = "Whether or not to hide items behind their boxsets.", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")] public bool? CollapseBoxSetItems { get; set; } - public string[] GetAllGenres() - { - return (AllGenres ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); - } - public string[] GetStudios() { return (Studios ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); } + public string[] GetStudioIds() + { + return (StudioIds ?? string.Empty).Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries); + } + public string[] GetPersonTypes() { return (PersonTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); } - public IEnumerable GetVideoTypes() + public VideoType[] GetVideoTypes() { var val = VideoTypes; @@ -250,7 +253,7 @@ namespace MediaBrowser.Api.UserLibrary return new VideoType[] { }; } - return val.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(v => (VideoType)Enum.Parse(typeof(VideoType), v, true)); + return val.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(v => (VideoType)Enum.Parse(typeof(VideoType), v, true)).ToArray(); } } @@ -471,8 +474,8 @@ namespace MediaBrowser.Api.UserLibrary Tags = request.GetTags(), OfficialRatings = request.GetOfficialRatings(), Genres = request.GetGenres(), - AllGenres = request.GetAllGenres(), Studios = request.GetStudios(), + StudioIds = request.GetStudioIds(), Person = request.Person, PersonTypes = request.GetPersonTypes(), Years = request.GetYears(), @@ -609,6 +612,8 @@ namespace MediaBrowser.Api.UserLibrary private bool ApplyAdditionalFilters(GetItems request, BaseItem i, User user, bool isPreFiltered, ILibraryManager libraryManager) { + var video = i as Video; + if (!isPreFiltered) { var mediaTypes = request.GetMediaTypes(); @@ -656,7 +661,6 @@ namespace MediaBrowser.Api.UserLibrary if (request.Is3D.HasValue) { var val = request.Is3D.Value; - var video = i as Video; if (video == null || val != video.Video3DFormat.HasValue) { @@ -667,7 +671,6 @@ namespace MediaBrowser.Api.UserLibrary if (request.IsHD.HasValue) { var val = request.IsHD.Value; - var video = i as Video; if (video == null || val != video.IsHD) { @@ -809,8 +812,6 @@ namespace MediaBrowser.Api.UserLibrary { var val = request.HasSubtitles.Value; - var video = i as Video; - if (video == null || val != video.HasSubtitles) { return false; @@ -930,25 +931,13 @@ namespace MediaBrowser.Api.UserLibrary return false; } - // Apply genre filter - var allGenres = request.GetAllGenres(); - if (allGenres.Length > 0 && !allGenres.All(v => i.Genres.Contains(v, StringComparer.OrdinalIgnoreCase))) + // Filter by VideoType + var videoTypes = request.GetVideoTypes(); + if (videoTypes.Length > 0 && (video == null || !videoTypes.Contains(video.VideoType))) { return false; } - // Filter by VideoType - if (!string.IsNullOrEmpty(request.VideoTypes)) - { - var types = request.VideoTypes.Split(','); - - var video = i as Video; - if (video == null || !types.Contains(video.VideoType.ToString(), StringComparer.OrdinalIgnoreCase)) - { - return false; - } - } - var imageTypes = request.GetImageTypes().ToList(); if (imageTypes.Count > 0) { @@ -965,6 +954,17 @@ namespace MediaBrowser.Api.UserLibrary return false; } + // Apply studio filter + var studioIds = request.GetStudioIds(); + if (studioIds.Length > 0 && !studioIds.Any(id => + { + var studioItem = libraryManager.GetItemById(id); + return studioItem != null && i.Studios.Contains(studioItem.Name, StringComparer.OrdinalIgnoreCase); + })) + { + return false; + } + // Apply year filter var years = request.GetYears(); if (years.Length > 0 && !(i.ProductionYear.HasValue && years.Contains(i.ProductionYear.Value))) @@ -1030,6 +1030,23 @@ namespace MediaBrowser.Api.UserLibrary } } + // Artists + if (!string.IsNullOrEmpty(request.ArtistIds)) + { + var artistIds = request.ArtistIds.Split('|'); + + var audio = i as IHasArtist; + + if (!(audio != null && artistIds.Any(id => + { + var artistItem = libraryManager.GetItemById(id); + return artistItem != null && audio.HasAnyArtist(artistItem.Name); + }))) + { + return false; + } + } + // Artists if (!string.IsNullOrEmpty(request.Artists)) { @@ -1037,7 +1054,7 @@ namespace MediaBrowser.Api.UserLibrary var audio = i as IHasArtist; - if (!(audio != null && artists.Any(audio.HasArtist))) + if (!(audio != null && artists.Any(audio.HasAnyArtist))) { return false; } diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index d868227d9..c033b144a 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -171,16 +171,6 @@ namespace MediaBrowser.Controller.Entities.Audio + (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name; } - /// - /// Determines whether the specified name has artist. - /// - /// The name. - /// true if the specified name has artist; otherwise, false. - public bool HasArtist(string name) - { - return AllArtists.Contains(name, StringComparer.OrdinalIgnoreCase); - } - /// /// Gets the user data key. /// diff --git a/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs b/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs index a20f05323..56921409a 100644 --- a/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs @@ -1,4 +1,6 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; +using System.Linq; namespace MediaBrowser.Controller.Entities.Audio { @@ -9,10 +11,20 @@ namespace MediaBrowser.Controller.Entities.Audio public interface IHasArtist { - bool HasArtist(string name); - List AllArtists { get; } - List Artists { get; } + List Artists { get; set; } + } + + public static class HasArtistExtensions + { + public static bool HasArtist(this IHasArtist hasArtist, string artist) + { + return hasArtist.Artists.Contains(artist, StringComparer.OrdinalIgnoreCase); + } + public static bool HasAnyArtist(this IHasArtist hasArtist, string artist) + { + return hasArtist.AllArtists.Contains(artist, StringComparer.OrdinalIgnoreCase); + } } } diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index e3f523b5a..dc3f13b01 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -120,16 +120,6 @@ namespace MediaBrowser.Controller.Entities.Audio get { return Parent as MusicArtist ?? UnknwonArtist; } } - /// - /// Determines whether the specified artist has artist. - /// - /// The artist. - /// true if the specified artist has artist; otherwise, false. - public bool HasArtist(string artist) - { - return AllArtists.Contains(artist, StringComparer.OrdinalIgnoreCase); - } - public List Artists { get; set; } /// diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs index fed9689b3..4185590ab 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs @@ -213,7 +213,7 @@ namespace MediaBrowser.Controller.Entities.Audio return i => { var hasArtist = i as IHasArtist; - return hasArtist != null && hasArtist.HasArtist(Name); + return hasArtist != null && hasArtist.HasAnyArtist(Name); }; } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index df28c282d..b1fa12884 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1455,7 +1455,8 @@ namespace MediaBrowser.Controller.Entities /// Task. public virtual Task ChangedExternally() { - return RefreshMetadata(CancellationToken.None); + ProviderManager.QueueRefresh(Id, new MetadataRefreshOptions()); + return Task.FromResult(true); } /// diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index e99c11e87..e1344009f 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -30,7 +30,6 @@ namespace MediaBrowser.Controller.Entities public string[] IncludeItemTypes { get; set; } public string[] ExcludeItemTypes { get; set; } public string[] Genres { get; set; } - public string[] AllGenres { get; set; } public bool? IsMissing { get; set; } public bool? IsUnaired { get; set; } @@ -66,6 +65,7 @@ namespace MediaBrowser.Controller.Entities public bool? HasParentalRating { get; set; } public string[] Studios { get; set; } + public string[] StudioIds { get; set; } public ImageType[] ImageTypes { get; set; } public VideoType[] VideoTypes { get; set; } public int[] Years { get; set; } @@ -80,9 +80,9 @@ namespace MediaBrowser.Controller.Entities MediaTypes = new string[] { }; IncludeItemTypes = new string[] { }; ExcludeItemTypes = new string[] { }; - AllGenres = new string[] { }; Genres = new string[] { }; Studios = new string[] { }; + StudioIds = new string[] { }; ImageTypes = new ImageType[] { }; VideoTypes = new VideoType[] { }; Years = new int[] { }; diff --git a/MediaBrowser.Controller/Entities/MusicVideo.cs b/MediaBrowser.Controller/Entities/MusicVideo.cs index 771c62fd6..b2cad02de 100644 --- a/MediaBrowser.Controller/Entities/MusicVideo.cs +++ b/MediaBrowser.Controller/Entities/MusicVideo.cs @@ -47,16 +47,6 @@ namespace MediaBrowser.Controller.Entities } } - /// - /// Determines whether the specified name has artist. - /// - /// The name. - /// true if the specified name has artist; otherwise, false. - public bool HasArtist(string name) - { - return AllArtists.Contains(name, StringComparer.OrdinalIgnoreCase); - } - /// /// Gets the user data key. /// diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs index d0378821f..9be30273a 100644 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ b/MediaBrowser.Controller/Entities/UserView.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.TV; +using MediaBrowser.Controller.Playlists; +using MediaBrowser.Controller.TV; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Querying; using System; @@ -15,6 +16,7 @@ namespace MediaBrowser.Controller.Entities public Guid? UserId { get; set; } public static ITVSeriesManager TVSeriesManager; + public static IPlaylistManager PlaylistManager; public bool ContainsDynamicCategories(User user) { @@ -30,7 +32,7 @@ namespace MediaBrowser.Controller.Entities parent = LibraryManager.GetItemById(ParentId) as Folder ?? parent; } - return new UserViewBuilder(UserViewManager, LiveTvManager, ChannelManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, CollectionManager) + return new UserViewBuilder(UserViewManager, LiveTvManager, ChannelManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, CollectionManager, PlaylistManager) .GetUserItems(parent, this, ViewType, query); } diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index 35ada4aef..12eae9a75 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -5,6 +5,7 @@ using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; +using MediaBrowser.Controller.Playlists; using MediaBrowser.Controller.TV; using MediaBrowser.Model.Channels; using MediaBrowser.Model.Entities; @@ -30,8 +31,9 @@ namespace MediaBrowser.Controller.Entities private readonly IUserDataManager _userDataManager; private readonly ITVSeriesManager _tvSeriesManager; private readonly ICollectionManager _collectionManager; + private readonly IPlaylistManager _playlistManager; - public UserViewBuilder(IUserViewManager userViewManager, ILiveTvManager liveTvManager, IChannelManager channelManager, ILibraryManager libraryManager, ILogger logger, IUserDataManager userDataManager, ITVSeriesManager tvSeriesManager, ICollectionManager collectionManager) + public UserViewBuilder(IUserViewManager userViewManager, ILiveTvManager liveTvManager, IChannelManager channelManager, ILibraryManager libraryManager, ILogger logger, IUserDataManager userDataManager, ITVSeriesManager tvSeriesManager, ICollectionManager collectionManager, IPlaylistManager playlistManager) { _userViewManager = userViewManager; _liveTvManager = liveTvManager; @@ -41,6 +43,7 @@ namespace MediaBrowser.Controller.Entities _userDataManager = userDataManager; _tvSeriesManager = tvSeriesManager; _collectionManager = collectionManager; + _playlistManager = playlistManager; } public async Task> GetUserItems(Folder queryParent, Folder displayParent, string viewType, InternalItemsQuery query) @@ -115,6 +118,9 @@ namespace MediaBrowser.Controller.Entities case CollectionType.Games: return await GetGameView(user, queryParent, query).ConfigureAwait(false); + case CollectionType.Playlists: + return await GetPlaylistsView(queryParent, user, query).ConfigureAwait(false); + case CollectionType.BoxSets: return await GetBoxsetView(queryParent, user, query).ConfigureAwait(false); @@ -572,6 +578,11 @@ namespace MediaBrowser.Controller.Entities return GetResult(items, queryParent, query); } + private async Task> GetPlaylistsView(Folder parent, User user, InternalItemsQuery query) + { + return GetResult(_playlistManager.GetPlaylists(user.Id.ToString("N")), parent, query); + } + private async Task> GetBoxsetView(Folder parent, User user, InternalItemsQuery query) { return GetResult(GetMediaFolders(user).SelectMany(i => @@ -935,11 +946,6 @@ namespace MediaBrowser.Controller.Entities return false; } - if (request.AllGenres.Length > 0) - { - return false; - } - if (request.Genres.Length > 0) { return false; @@ -1050,6 +1056,11 @@ namespace MediaBrowser.Controller.Entities return false; } + if (request.StudioIds.Length > 0) + { + return false; + } + if (request.VideoTypes.Length > 0) { return false; @@ -1569,12 +1580,6 @@ namespace MediaBrowser.Controller.Entities return false; } - // Apply genre filter - if (query.AllGenres.Length > 0 && !query.AllGenres.All(v => item.Genres.Contains(v, StringComparer.OrdinalIgnoreCase))) - { - return false; - } - // Filter by VideoType if (query.VideoTypes.Length > 0) { @@ -1596,6 +1601,16 @@ namespace MediaBrowser.Controller.Entities return false; } + // Apply studio filter + if (query.StudioIds.Length > 0 && !query.StudioIds.Any(id => + { + var studioItem = libraryManager.GetItemById(id); + return studioItem != null && item.Studios.Contains(studioItem.Name, StringComparer.OrdinalIgnoreCase); + })) + { + return false; + } + // Apply year filter if (query.Years.Length > 0) { @@ -1714,7 +1729,7 @@ namespace MediaBrowser.Controller.Entities var parent = user.RootFolder; - //list.Add(await GetUserView(SpecialFolder.LiveTvNowPlaying, user, "0", parent).ConfigureAwait(false)); + //list.Add(await GetUserSubView(SpecialFolder.LiveTvNowPlaying, user, "0", parent).ConfigureAwait(false)); list.Add(await GetUserView(SpecialFolder.LiveTvChannels, user, string.Empty, parent).ConfigureAwait(false)); list.Add(await GetUserView(SpecialFolder.LiveTvRecordingGroups, user, string.Empty, parent).ConfigureAwait(false)); @@ -1723,7 +1738,7 @@ namespace MediaBrowser.Controller.Entities private async Task GetUserView(string name, string type, User user, string sortName, BaseItem parent) { - var view = await _userViewManager.GetUserView(name, parent.Id.ToString("N"), type, user, sortName, CancellationToken.None) + var view = await _userViewManager.GetUserSubView(name, parent.Id.ToString("N"), type, user, sortName, CancellationToken.None) .ConfigureAwait(false); return view; @@ -1731,7 +1746,7 @@ namespace MediaBrowser.Controller.Entities private async Task GetUserView(string type, User user, string sortName, BaseItem parent) { - var view = await _userViewManager.GetUserView(parent.Id.ToString("N"), type, user, sortName, CancellationToken.None) + var view = await _userViewManager.GetUserSubView(parent.Id.ToString("N"), type, user, sortName, CancellationToken.None) .ConfigureAwait(false); return view; diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 9c8ed45a5..d16589f07 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -302,7 +302,7 @@ namespace MediaBrowser.Controller.Library IEnumerable ReplaceVideosWithPrimaryVersions(IEnumerable items); /// - /// Gets the special folder. + /// Gets the named view. /// /// The user. /// The name. @@ -311,7 +311,7 @@ namespace MediaBrowser.Controller.Library /// Name of the sort. /// The cancellation token. /// Task<UserView>. - Task GetSpecialFolder(User user, + Task GetNamedView(User user, string name, string parentId, string viewType, @@ -321,12 +321,14 @@ namespace MediaBrowser.Controller.Library /// /// Gets the named view. /// + /// The user. /// The name. /// Type of the view. /// Name of the sort. /// The cancellation token. /// Task<UserView>. - Task GetNamedView(string name, + Task GetNamedView(User user, + string name, string viewType, string sortName, CancellationToken cancellationToken); diff --git a/MediaBrowser.Controller/Library/IUserViewManager.cs b/MediaBrowser.Controller/Library/IUserViewManager.cs index f55c17924..f0b862c2d 100644 --- a/MediaBrowser.Controller/Library/IUserViewManager.cs +++ b/MediaBrowser.Controller/Library/IUserViewManager.cs @@ -12,12 +12,10 @@ namespace MediaBrowser.Controller.Library { Task> GetUserViews(UserViewQuery query, CancellationToken cancellationToken); - Task GetUserView(string name, string parentId, string type, User user, string sortName, + Task GetUserSubView(string name, string parentId, string type, User user, string sortName, CancellationToken cancellationToken); - Task GetUserView(string type, string sortName, CancellationToken cancellationToken); - - Task GetUserView(string category, string type, User user, string sortName, CancellationToken cancellationToken); + Task GetUserSubView(string category, string type, User user, string sortName, CancellationToken cancellationToken); List>> GetLatestItems(LatestItemsQuery request); } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index f046c76fc..678d7841c 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -247,22 +247,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -350,6 +395,7 @@ + diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs index 3479902cb..fdc36db35 100644 --- a/MediaBrowser.Controller/Playlists/Playlist.cs +++ b/MediaBrowser.Controller/Playlists/Playlist.cs @@ -106,7 +106,7 @@ namespace MediaBrowser.Controller.Playlists Func filter = i => { var audio = i as Audio; - return audio != null && audio.HasArtist(musicArtist.Name); + return audio != null && audio.HasAnyArtist(musicArtist.Name); }; var items = user == null diff --git a/MediaBrowser.Controller/Providers/AlbumInfo.cs b/MediaBrowser.Controller/Providers/AlbumInfo.cs new file mode 100644 index 000000000..b88477409 --- /dev/null +++ b/MediaBrowser.Controller/Providers/AlbumInfo.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; + +namespace MediaBrowser.Controller.Providers +{ + public class AlbumInfo : ItemLookupInfo + { + /// + /// Gets or sets the album artist. + /// + /// The album artist. + public List AlbumArtists { get; set; } + + /// + /// Gets or sets the artist provider ids. + /// + /// The artist provider ids. + public Dictionary ArtistProviderIds { get; set; } + public List SongInfos { get; set; } + + public AlbumInfo() + { + ArtistProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase); + SongInfos = new List(); + AlbumArtists = new List(); + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/ArtistInfo.cs b/MediaBrowser.Controller/Providers/ArtistInfo.cs new file mode 100644 index 000000000..8a4abd5c6 --- /dev/null +++ b/MediaBrowser.Controller/Providers/ArtistInfo.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; + +namespace MediaBrowser.Controller.Providers +{ + public class ArtistInfo : ItemLookupInfo + { + public List SongInfos { get; set; } + + public ArtistInfo() + { + SongInfos = new List(); + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/BookInfo.cs b/MediaBrowser.Controller/Providers/BookInfo.cs new file mode 100644 index 000000000..52519bcb0 --- /dev/null +++ b/MediaBrowser.Controller/Providers/BookInfo.cs @@ -0,0 +1,7 @@ +namespace MediaBrowser.Controller.Providers +{ + public class BookInfo : ItemLookupInfo + { + public string SeriesName { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/BoxSetInfo.cs b/MediaBrowser.Controller/Providers/BoxSetInfo.cs new file mode 100644 index 000000000..f604231de --- /dev/null +++ b/MediaBrowser.Controller/Providers/BoxSetInfo.cs @@ -0,0 +1,7 @@ +namespace MediaBrowser.Controller.Providers +{ + public class BoxSetInfo : ItemLookupInfo + { + + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/ChannelItemLookupInfo.cs b/MediaBrowser.Controller/Providers/ChannelItemLookupInfo.cs new file mode 100644 index 000000000..6c972f3bf --- /dev/null +++ b/MediaBrowser.Controller/Providers/ChannelItemLookupInfo.cs @@ -0,0 +1,11 @@ +using MediaBrowser.Model.Channels; +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.Controller.Providers +{ + public class ChannelItemLookupInfo : ItemLookupInfo + { + public ChannelMediaContentType ContentType { get; set; } + public ExtraType ExtraType { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/DirectoryService.cs b/MediaBrowser.Controller/Providers/DirectoryService.cs index 06ea7be02..9e549dcf3 100644 --- a/MediaBrowser.Controller/Providers/DirectoryService.cs +++ b/MediaBrowser.Controller/Providers/DirectoryService.cs @@ -7,16 +7,6 @@ using System.Linq; namespace MediaBrowser.Controller.Providers { - public interface IDirectoryService - { - IEnumerable GetFileSystemEntries(string path); - IEnumerable GetFiles(string path); - IEnumerable GetDirectories(string path); - IEnumerable GetFiles(string path, bool clearCache); - FileSystemInfo GetFile(string path); - Dictionary GetFileSystemDictionary(string path); - } - public class DirectoryService : IDirectoryService { private readonly ILogger _logger; diff --git a/MediaBrowser.Controller/Providers/DynamicImageInfo.cs b/MediaBrowser.Controller/Providers/DynamicImageInfo.cs new file mode 100644 index 000000000..14b4c6afb --- /dev/null +++ b/MediaBrowser.Controller/Providers/DynamicImageInfo.cs @@ -0,0 +1,10 @@ +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.Controller.Providers +{ + public class DynamicImageInfo + { + public string ImageId { get; set; } + public ImageType Type { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/DynamicImageResponse.cs b/MediaBrowser.Controller/Providers/DynamicImageResponse.cs new file mode 100644 index 000000000..71a937cd9 --- /dev/null +++ b/MediaBrowser.Controller/Providers/DynamicImageResponse.cs @@ -0,0 +1,35 @@ +using System; +using System.IO; +using MediaBrowser.Model.Drawing; + +namespace MediaBrowser.Controller.Providers +{ + public class DynamicImageResponse + { + public string Path { get; set; } + public Stream Stream { get; set; } + public ImageFormat Format { get; set; } + public bool HasImage { get; set; } + public string InternalCacheKey { get; set; } + + public void SetFormatFromMimeType(string mimeType) + { + if (mimeType.EndsWith("gif", StringComparison.OrdinalIgnoreCase)) + { + Format = ImageFormat.Gif; + } + else if (mimeType.EndsWith("bmp", StringComparison.OrdinalIgnoreCase)) + { + Format = ImageFormat.Bmp; + } + else if (mimeType.EndsWith("png", StringComparison.OrdinalIgnoreCase)) + { + Format = ImageFormat.Png; + } + else + { + Format = ImageFormat.Jpg; + } + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/EpisodeIdentity.cs b/MediaBrowser.Controller/Providers/EpisodeIdentity.cs new file mode 100644 index 000000000..53f469e95 --- /dev/null +++ b/MediaBrowser.Controller/Providers/EpisodeIdentity.cs @@ -0,0 +1,12 @@ +namespace MediaBrowser.Controller.Providers +{ + public class EpisodeIdentity : IItemIdentity + { + public string Type { get; set; } + + public string SeriesId { get; set; } + public int? SeasonIndex { get; set; } + public int IndexNumber { get; set; } + public int? IndexNumberEnd { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/EpisodeInfo.cs b/MediaBrowser.Controller/Providers/EpisodeInfo.cs new file mode 100644 index 000000000..88a7cbab7 --- /dev/null +++ b/MediaBrowser.Controller/Providers/EpisodeInfo.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Providers +{ + public class EpisodeInfo : ItemLookupInfo, IHasIdentities + { + private List _identities = new List(); + + public Dictionary SeriesProviderIds { get; set; } + + public int? IndexNumberEnd { get; set; } + public int? AnimeSeriesIndex { get; set; } + + public EpisodeInfo() + { + SeriesProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase); + } + + public IEnumerable Identities + { + get { return _identities; } + } + + public async Task FindIdentities(IProviderManager providerManager, CancellationToken cancellationToken) + { + var identifier = new ItemIdentifier(); + _identities = (await identifier.FindIdentities(this, providerManager, cancellationToken)).ToList(); + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/ExtraInfo.cs b/MediaBrowser.Controller/Providers/ExtraInfo.cs new file mode 100644 index 000000000..1fbe6e93a --- /dev/null +++ b/MediaBrowser.Controller/Providers/ExtraInfo.cs @@ -0,0 +1,15 @@ +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.Controller.Providers +{ + public class ExtraInfo + { + public string Path { get; set; } + + public LocationType LocationType { get; set; } + + public bool IsDownloadable { get; set; } + + public ExtraType ExtraType { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/ExtraSource.cs b/MediaBrowser.Controller/Providers/ExtraSource.cs new file mode 100644 index 000000000..901af60f8 --- /dev/null +++ b/MediaBrowser.Controller/Providers/ExtraSource.cs @@ -0,0 +1,9 @@ +namespace MediaBrowser.Controller.Providers +{ + public enum ExtraSource + { + Local = 1, + Metadata = 2, + Remote = 3 + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/GameInfo.cs b/MediaBrowser.Controller/Providers/GameInfo.cs new file mode 100644 index 000000000..771cf6cec --- /dev/null +++ b/MediaBrowser.Controller/Providers/GameInfo.cs @@ -0,0 +1,11 @@ +namespace MediaBrowser.Controller.Providers +{ + public class GameInfo : ItemLookupInfo + { + /// + /// Gets or sets the game system. + /// + /// The game system. + public string GameSystem { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/GameSystemInfo.cs b/MediaBrowser.Controller/Providers/GameSystemInfo.cs new file mode 100644 index 000000000..efe2635cd --- /dev/null +++ b/MediaBrowser.Controller/Providers/GameSystemInfo.cs @@ -0,0 +1,11 @@ +namespace MediaBrowser.Controller.Providers +{ + public class GameSystemInfo : ItemLookupInfo + { + /// + /// Gets or sets the path. + /// + /// The path. + public string Path { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/ICustomMetadataProvider.cs b/MediaBrowser.Controller/Providers/ICustomMetadataProvider.cs index 3ce6ac46b..c9393f4c3 100644 --- a/MediaBrowser.Controller/Providers/ICustomMetadataProvider.cs +++ b/MediaBrowser.Controller/Providers/ICustomMetadataProvider.cs @@ -21,9 +21,4 @@ namespace MediaBrowser.Controller.Providers /// Task{ItemUpdateType}. Task FetchAsync(TItemType item, MetadataRefreshOptions options, CancellationToken cancellationToken); } - - public interface IPreRefreshProvider : ICustomMetadataProvider - { - - } } diff --git a/MediaBrowser.Controller/Providers/IDirectoryService.cs b/MediaBrowser.Controller/Providers/IDirectoryService.cs new file mode 100644 index 000000000..343cf361f --- /dev/null +++ b/MediaBrowser.Controller/Providers/IDirectoryService.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.IO; + +namespace MediaBrowser.Controller.Providers +{ + public interface IDirectoryService + { + IEnumerable GetFileSystemEntries(string path); + IEnumerable GetFiles(string path); + IEnumerable GetDirectories(string path); + IEnumerable GetFiles(string path, bool clearCache); + FileSystemInfo GetFile(string path); + Dictionary GetFileSystemDictionary(string path); + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/IDynamicImageProvider.cs b/MediaBrowser.Controller/Providers/IDynamicImageProvider.cs new file mode 100644 index 000000000..9c3f94763 --- /dev/null +++ b/MediaBrowser.Controller/Providers/IDynamicImageProvider.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.Controller.Providers +{ + public interface IDynamicImageProvider : IImageProvider + { + /// + /// Gets the supported images. + /// + /// The item. + /// IEnumerable{ImageType}. + IEnumerable GetSupportedImages(IHasImages item); + + /// + /// Gets the image. + /// + /// The item. + /// The type. + /// The cancellation token. + /// Task{DynamicImageResponse}. + Task GetImage(IHasImages item, ImageType type, CancellationToken cancellationToken); + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/IExtrasProvider.cs b/MediaBrowser.Controller/Providers/IExtrasProvider.cs index 953bf02a1..3b72232c2 100644 --- a/MediaBrowser.Controller/Providers/IExtrasProvider.cs +++ b/MediaBrowser.Controller/Providers/IExtrasProvider.cs @@ -1,5 +1,4 @@ using MediaBrowser.Controller.Entities; -using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Providers { @@ -18,22 +17,4 @@ namespace MediaBrowser.Controller.Providers /// true if XXXX, false otherwise. bool Supports(IHasMetadata item); } - - public enum ExtraSource - { - Local = 1, - Metadata = 2, - Remote = 3 - } - - public class ExtraInfo - { - public string Path { get; set; } - - public LocationType LocationType { get; set; } - - public bool IsDownloadable { get; set; } - - public ExtraType ExtraType { get; set; } - } } diff --git a/MediaBrowser.Controller/Providers/IHasChangeMonitor.cs b/MediaBrowser.Controller/Providers/IHasChangeMonitor.cs index d914abf61..aa0b0e3c9 100644 --- a/MediaBrowser.Controller/Providers/IHasChangeMonitor.cs +++ b/MediaBrowser.Controller/Providers/IHasChangeMonitor.cs @@ -14,16 +14,4 @@ namespace MediaBrowser.Controller.Providers /// true if the specified item has changed; otherwise, false. bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date); } - - public interface IHasItemChangeMonitor - { - /// - /// Determines whether the specified item has changed. - /// - /// The item. - /// The status. - /// The directory service. - /// true if the specified item has changed; otherwise, false. - bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService); - } } diff --git a/MediaBrowser.Controller/Providers/IHasIdentities.cs b/MediaBrowser.Controller/Providers/IHasIdentities.cs new file mode 100644 index 000000000..36f940dd3 --- /dev/null +++ b/MediaBrowser.Controller/Providers/IHasIdentities.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Providers +{ + public interface IHasIdentities + where TIdentity : IItemIdentity + { + IEnumerable Identities { get; } + + Task FindIdentities(IProviderManager providerManager, CancellationToken cancellationToken); + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/IHasItemChangeMonitor.cs b/MediaBrowser.Controller/Providers/IHasItemChangeMonitor.cs new file mode 100644 index 000000000..4c7069dd6 --- /dev/null +++ b/MediaBrowser.Controller/Providers/IHasItemChangeMonitor.cs @@ -0,0 +1,16 @@ +using MediaBrowser.Controller.Entities; + +namespace MediaBrowser.Controller.Providers +{ + public interface IHasItemChangeMonitor + { + /// + /// Determines whether the specified item has changed. + /// + /// The item. + /// The status. + /// The directory service. + /// true if the specified item has changed; otherwise, false. + bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService); + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/IHasLookupInfo.cs b/MediaBrowser.Controller/Providers/IHasLookupInfo.cs new file mode 100644 index 000000000..afce49852 --- /dev/null +++ b/MediaBrowser.Controller/Providers/IHasLookupInfo.cs @@ -0,0 +1,8 @@ +namespace MediaBrowser.Controller.Providers +{ + public interface IHasLookupInfo + where TLookupInfoType : ItemLookupInfo, new() + { + TLookupInfoType GetLookupInfo(); + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/IHasOrder.cs b/MediaBrowser.Controller/Providers/IHasOrder.cs new file mode 100644 index 000000000..cb5298dd3 --- /dev/null +++ b/MediaBrowser.Controller/Providers/IHasOrder.cs @@ -0,0 +1,7 @@ +namespace MediaBrowser.Controller.Providers +{ + public interface IHasOrder + { + int Order { get; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/IImageFileSaver.cs b/MediaBrowser.Controller/Providers/IImageFileSaver.cs new file mode 100644 index 000000000..3e11d8bf8 --- /dev/null +++ b/MediaBrowser.Controller/Providers/IImageFileSaver.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Drawing; +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.Controller.Providers +{ + public interface IImageFileSaver : IImageSaver + { + /// + /// Gets the save paths. + /// + /// The item. + /// The type. + /// The format. + /// The index. + /// IEnumerable{System.String}. + IEnumerable GetSavePaths(IHasImages item, ImageType type, ImageFormat format, int index); + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/IImageSaver.cs b/MediaBrowser.Controller/Providers/IImageSaver.cs index a983de63e..62017160f 100644 --- a/MediaBrowser.Controller/Providers/IImageSaver.cs +++ b/MediaBrowser.Controller/Providers/IImageSaver.cs @@ -1,9 +1,4 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Model.Drawing; -using MediaBrowser.Model.Entities; -using System.Collections.Generic; - -namespace MediaBrowser.Controller.Providers +namespace MediaBrowser.Controller.Providers { public interface IImageSaver { @@ -13,17 +8,4 @@ namespace MediaBrowser.Controller.Providers /// The name. string Name { get; } } - - public interface IImageFileSaver : IImageSaver - { - /// - /// Gets the save paths. - /// - /// The item. - /// The type. - /// The format. - /// The index. - /// IEnumerable{System.String}. - IEnumerable GetSavePaths(IHasImages item, ImageType type, ImageFormat format, int index); - } } diff --git a/MediaBrowser.Controller/Providers/IItemIdentity.cs b/MediaBrowser.Controller/Providers/IItemIdentity.cs new file mode 100644 index 000000000..cab189c84 --- /dev/null +++ b/MediaBrowser.Controller/Providers/IItemIdentity.cs @@ -0,0 +1,7 @@ +namespace MediaBrowser.Controller.Providers +{ + public interface IItemIdentity + { + string Type { get; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/IItemIdentityConverter.cs b/MediaBrowser.Controller/Providers/IItemIdentityConverter.cs new file mode 100644 index 000000000..30e96b9e5 --- /dev/null +++ b/MediaBrowser.Controller/Providers/IItemIdentityConverter.cs @@ -0,0 +1,4 @@ +namespace MediaBrowser.Controller.Providers +{ + public interface IItemIdentityConverter : IHasOrder { } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/IItemIdentityProvider.cs b/MediaBrowser.Controller/Providers/IItemIdentityProvider.cs new file mode 100644 index 000000000..9d437c208 --- /dev/null +++ b/MediaBrowser.Controller/Providers/IItemIdentityProvider.cs @@ -0,0 +1,4 @@ +namespace MediaBrowser.Controller.Providers +{ + public interface IItemIdentityProvider : IHasOrder { } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/ILocalImageFileProvider.cs b/MediaBrowser.Controller/Providers/ILocalImageFileProvider.cs new file mode 100644 index 000000000..7e5d82843 --- /dev/null +++ b/MediaBrowser.Controller/Providers/ILocalImageFileProvider.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using MediaBrowser.Controller.Entities; + +namespace MediaBrowser.Controller.Providers +{ + public interface ILocalImageFileProvider : ILocalImageProvider + { + List GetImages(IHasImages item, IDirectoryService directoryService); + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/ILocalImageProvider.cs b/MediaBrowser.Controller/Providers/ILocalImageProvider.cs index d1345d7a6..1027a4cb2 100644 --- a/MediaBrowser.Controller/Providers/ILocalImageProvider.cs +++ b/MediaBrowser.Controller/Providers/ILocalImageProvider.cs @@ -1,13 +1,4 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Model.Drawing; -using MediaBrowser.Model.Entities; -using System; -using System.Collections.Generic; -using System.IO; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Controller.Providers +namespace MediaBrowser.Controller.Providers { /// /// This is just a marker interface @@ -15,68 +6,4 @@ namespace MediaBrowser.Controller.Providers public interface ILocalImageProvider : IImageProvider { } - - public interface ILocalImageFileProvider : ILocalImageProvider - { - List GetImages(IHasImages item, IDirectoryService directoryService); - } - - public class LocalImageInfo - { - public FileSystemInfo FileInfo { get; set; } - public ImageType Type { get; set; } - } - - public interface IDynamicImageProvider : IImageProvider - { - /// - /// Gets the supported images. - /// - /// The item. - /// IEnumerable{ImageType}. - IEnumerable GetSupportedImages(IHasImages item); - - /// - /// Gets the image. - /// - /// The item. - /// The type. - /// The cancellation token. - /// Task{DynamicImageResponse}. - Task GetImage(IHasImages item, ImageType type, CancellationToken cancellationToken); - } - - public class DynamicImageInfo - { - public string ImageId { get; set; } - public ImageType Type { get; set; } - } - - public class DynamicImageResponse - { - public string Path { get; set; } - public Stream Stream { get; set; } - public ImageFormat Format { get; set; } - public bool HasImage { get; set; } - - public void SetFormatFromMimeType(string mimeType) - { - if (mimeType.EndsWith("gif", StringComparison.OrdinalIgnoreCase)) - { - Format = ImageFormat.Gif; - } - else if (mimeType.EndsWith("bmp", StringComparison.OrdinalIgnoreCase)) - { - Format = ImageFormat.Bmp; - } - else if (mimeType.EndsWith("png", StringComparison.OrdinalIgnoreCase)) - { - Format = ImageFormat.Png; - } - else - { - Format = ImageFormat.Jpg; - } - } - } } diff --git a/MediaBrowser.Controller/Providers/ILocalMetadataProvider.cs b/MediaBrowser.Controller/Providers/ILocalMetadataProvider.cs index 61bc3b87b..3a8ef7325 100644 --- a/MediaBrowser.Controller/Providers/ILocalMetadataProvider.cs +++ b/MediaBrowser.Controller/Providers/ILocalMetadataProvider.cs @@ -1,6 +1,4 @@ using MediaBrowser.Controller.Entities; -using MediaBrowser.Model.Entities; -using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; @@ -24,29 +22,4 @@ namespace MediaBrowser.Controller.Providers IDirectoryService directoryService, CancellationToken cancellationToken); } - - public class ItemInfo - { - public string Path { get; set; } - - public bool IsInMixedFolder { get; set; } - } - - public class LocalMetadataResult - where T : IHasMetadata - { - public bool HasMetadata { get; set; } - public T Item { get; set; } - - public List Images { get; set; } - public List Chapters { get; set; } - public List UserDataLIst { get; set; } - - public LocalMetadataResult() - { - Images = new List(); - Chapters = new List(); - UserDataLIst = new List(); - } - } } diff --git a/MediaBrowser.Controller/Providers/IMetadataProvider.cs b/MediaBrowser.Controller/Providers/IMetadataProvider.cs index 52cd6fcea..26f43d820 100644 --- a/MediaBrowser.Controller/Providers/IMetadataProvider.cs +++ b/MediaBrowser.Controller/Providers/IMetadataProvider.cs @@ -19,15 +19,4 @@ namespace MediaBrowser.Controller.Providers where TItemType : IHasMetadata { } - - public interface IHasOrder - { - int Order { get; } - } - - public class MetadataResult - { - public bool HasMetadata { get; set; } - public T Item { get; set; } - } } diff --git a/MediaBrowser.Controller/Providers/IPreRefreshProvider.cs b/MediaBrowser.Controller/Providers/IPreRefreshProvider.cs new file mode 100644 index 000000000..608674905 --- /dev/null +++ b/MediaBrowser.Controller/Providers/IPreRefreshProvider.cs @@ -0,0 +1,7 @@ +namespace MediaBrowser.Controller.Providers +{ + public interface IPreRefreshProvider : ICustomMetadataProvider + { + + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs index 38ac958b3..e510a8995 100644 --- a/MediaBrowser.Controller/Providers/IProviderManager.cs +++ b/MediaBrowser.Controller/Providers/IProviderManager.cs @@ -4,6 +4,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Providers; +using System; using System.Collections.Generic; using System.IO; using System.Threading; @@ -16,6 +17,13 @@ namespace MediaBrowser.Controller.Providers /// public interface IProviderManager { + /// + /// Queues the refresh. + /// + /// The item identifier. + /// The options. + void QueueRefresh(Guid itemId, MetadataRefreshOptions options); + /// /// Refreshes the metadata. /// diff --git a/MediaBrowser.Controller/Providers/IRemoteMetadataProvider.cs b/MediaBrowser.Controller/Providers/IRemoteMetadataProvider.cs index 0ff7ee5a9..5e2e1b4c7 100644 --- a/MediaBrowser.Controller/Providers/IRemoteMetadataProvider.cs +++ b/MediaBrowser.Controller/Providers/IRemoteMetadataProvider.cs @@ -1,5 +1,4 @@ -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities; using MediaBrowser.Model.Providers; using System.Collections.Generic; using System.Threading; @@ -18,37 +17,9 @@ namespace MediaBrowser.Controller.Providers Task> GetMetadata(TLookupInfoType info, CancellationToken cancellationToken); } - public interface IRemoteSearchProvider : IMetadataProvider - { - /// - /// Gets the image response. - /// - /// The URL. - /// The cancellation token. - /// Task{HttpResponseInfo}. - Task GetImageResponse(string url, CancellationToken cancellationToken); - } - public interface IRemoteSearchProvider : IRemoteSearchProvider where TLookupInfoType : ItemLookupInfo { Task> GetSearchResults(TLookupInfoType searchInfo, CancellationToken cancellationToken); } - - public class RemoteSearchQuery - where T : ItemLookupInfo - { - public T SearchInfo { get; set; } - - /// - /// If set will only search within the given provider - /// - public string SearchProviderName { get; set; } - - /// - /// Gets or sets a value indicating whether [include disabled providers]. - /// - /// true if [include disabled providers]; otherwise, false. - public bool IncludeDisabledProviders { get; set; } - } } diff --git a/MediaBrowser.Controller/Providers/IRemoteSearchProvider.cs b/MediaBrowser.Controller/Providers/IRemoteSearchProvider.cs new file mode 100644 index 000000000..0077def42 --- /dev/null +++ b/MediaBrowser.Controller/Providers/IRemoteSearchProvider.cs @@ -0,0 +1,17 @@ +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Common.Net; + +namespace MediaBrowser.Controller.Providers +{ + public interface IRemoteSearchProvider : IMetadataProvider + { + /// + /// Gets the image response. + /// + /// The URL. + /// The cancellation token. + /// Task{HttpResponseInfo}. + Task GetImageResponse(string url, CancellationToken cancellationToken); + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/ISeriesOrderManager.cs b/MediaBrowser.Controller/Providers/ISeriesOrderManager.cs index a3adab1b9..235d0ada5 100644 --- a/MediaBrowser.Controller/Providers/ISeriesOrderManager.cs +++ b/MediaBrowser.Controller/Providers/ISeriesOrderManager.cs @@ -7,17 +7,6 @@ using MediaBrowser.Common; namespace MediaBrowser.Controller.Providers { - public interface ISeriesOrderProvider - { - string OrderType { get; } - Task FindSeriesIndex(string seriesName); - } - - public static class SeriesOrderTypes - { - public const string Anime = "Anime"; - } - public interface ISeriesOrderManager { Task FindSeriesIndex(string orderType, string seriesName); diff --git a/MediaBrowser.Controller/Providers/ISeriesOrderProvider.cs b/MediaBrowser.Controller/Providers/ISeriesOrderProvider.cs new file mode 100644 index 000000000..ee0f3c197 --- /dev/null +++ b/MediaBrowser.Controller/Providers/ISeriesOrderProvider.cs @@ -0,0 +1,10 @@ +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Providers +{ + public interface ISeriesOrderProvider + { + string OrderType { get; } + Task FindSeriesIndex(string seriesName); + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/ImageRefreshMode.cs b/MediaBrowser.Controller/Providers/ImageRefreshMode.cs new file mode 100644 index 000000000..df10c91f6 --- /dev/null +++ b/MediaBrowser.Controller/Providers/ImageRefreshMode.cs @@ -0,0 +1,25 @@ +namespace MediaBrowser.Controller.Providers +{ + public enum ImageRefreshMode + { + /// + /// The none + /// + None = 0, + + /// + /// The default + /// + Default = 1, + + /// + /// Existing images will be validated + /// + ValidationOnly = 2, + + /// + /// All providers will be executed to search for new metadata + /// + FullRefresh = 3 + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs b/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs new file mode 100644 index 000000000..a66cc6f22 --- /dev/null +++ b/MediaBrowser.Controller/Providers/ImageRefreshOptions.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.Controller.Providers +{ + public class ImageRefreshOptions + { + public ImageRefreshMode ImageRefreshMode { get; set; } + public IDirectoryService DirectoryService { get; private set; } + + public bool ReplaceAllImages { get; set; } + + public List ReplaceImages { get; set; } + + public ImageRefreshOptions(IDirectoryService directoryService) + { + ImageRefreshMode = ImageRefreshMode.Default; + DirectoryService = directoryService; + + ReplaceImages = new List(); + } + + public bool IsReplacingImage(ImageType type) + { + return ImageRefreshMode == ImageRefreshMode.FullRefresh && + (ReplaceAllImages || ReplaceImages.Contains(type)); + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/ItemIdentities.cs b/MediaBrowser.Controller/Providers/ItemIdentities.cs index 8d24f6c1f..939fd3b8f 100644 --- a/MediaBrowser.Controller/Providers/ItemIdentities.cs +++ b/MediaBrowser.Controller/Providers/ItemIdentities.cs @@ -1,24 +1,7 @@ -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; +using System.Threading.Tasks; namespace MediaBrowser.Controller.Providers { - public interface IItemIdentity - { - string Type { get; } - } - - public interface IHasIdentities - where TIdentity : IItemIdentity - { - IEnumerable Identities { get; } - - Task FindIdentities(IProviderManager providerManager, CancellationToken cancellationToken); - } - - public interface IItemIdentityProvider : IHasOrder { } - public interface IItemIdentityProvider : IItemIdentityProvider where TLookupInfo : ItemLookupInfo where TIdentity : IItemIdentity @@ -26,8 +9,6 @@ namespace MediaBrowser.Controller.Providers Task FindIdentity(TLookupInfo info); } - public interface IItemIdentityConverter : IHasOrder { } - public interface IItemIdentityConverter : IItemIdentityConverter where TIdentity : IItemIdentity { diff --git a/MediaBrowser.Controller/Providers/ItemInfo.cs b/MediaBrowser.Controller/Providers/ItemInfo.cs new file mode 100644 index 000000000..113a7bb8e --- /dev/null +++ b/MediaBrowser.Controller/Providers/ItemInfo.cs @@ -0,0 +1,9 @@ +namespace MediaBrowser.Controller.Providers +{ + public class ItemInfo + { + public string Path { get; set; } + + public bool IsInMixedFolder { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/ItemLookupInfo.cs b/MediaBrowser.Controller/Providers/ItemLookupInfo.cs index 649096a75..91dc33214 100644 --- a/MediaBrowser.Controller/Providers/ItemLookupInfo.cs +++ b/MediaBrowser.Controller/Providers/ItemLookupInfo.cs @@ -1,8 +1,4 @@ -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Model.Channels; -using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Entities; using System; using System.Collections.Generic; @@ -43,204 +39,4 @@ namespace MediaBrowser.Controller.Providers ProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase); } } - - public interface IHasLookupInfo - where TLookupInfoType : ItemLookupInfo, new() - { - TLookupInfoType GetLookupInfo(); - } - - public class ArtistInfo : ItemLookupInfo - { - public List SongInfos { get; set; } - - public ArtistInfo() - { - SongInfos = new List(); - } - } - - public class AlbumInfo : ItemLookupInfo - { - /// - /// Gets or sets the album artist. - /// - /// The album artist. - public List AlbumArtists { get; set; } - - /// - /// Gets or sets the artist provider ids. - /// - /// The artist provider ids. - public Dictionary ArtistProviderIds { get; set; } - public List SongInfos { get; set; } - - public AlbumInfo() - { - ArtistProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase); - SongInfos = new List(); - AlbumArtists = new List(); - } - } - - public class GameInfo : ItemLookupInfo - { - /// - /// Gets or sets the game system. - /// - /// The game system. - public string GameSystem { get; set; } - } - - public class GameSystemInfo : ItemLookupInfo - { - /// - /// Gets or sets the path. - /// - /// The path. - public string Path { get; set; } - } - - public class EpisodeInfo : ItemLookupInfo, IHasIdentities - { - private List _identities = new List(); - - public Dictionary SeriesProviderIds { get; set; } - - public int? IndexNumberEnd { get; set; } - public int? AnimeSeriesIndex { get; set; } - - public EpisodeInfo() - { - SeriesProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase); - } - - public IEnumerable Identities - { - get { return _identities; } - } - - public async Task FindIdentities(IProviderManager providerManager, CancellationToken cancellationToken) - { - var identifier = new ItemIdentifier(); - _identities = (await identifier.FindIdentities(this, providerManager, cancellationToken)).ToList(); - } - } - - public class EpisodeIdentity : IItemIdentity - { - public string Type { get; set; } - - public string SeriesId { get; set; } - public int? SeasonIndex { get; set; } - public int IndexNumber { get; set; } - public int? IndexNumberEnd { get; set; } - } - - public class SongInfo : ItemLookupInfo - { - public List AlbumArtists { get; set; } - public string Album { get; set; } - public List Artists { get; set; } - - public SongInfo() - { - Artists = new List(); - AlbumArtists = new List(); - } - } - - public class SeriesInfo : ItemLookupInfo, IHasIdentities - { - private List _identities = new List(); - - public int? AnimeSeriesIndex { get; set; } - - public IEnumerable Identities - { - get { return _identities; } - } - - public async Task FindIdentities(IProviderManager providerManager, CancellationToken cancellationToken) - { - var identifier = new ItemIdentifier(); - _identities = (await identifier.FindIdentities(this, providerManager, cancellationToken)).ToList(); - } - } - - public class SeriesIdentity : IItemIdentity - { - public string Type { get; set; } - - public string Id { get; set; } - } - - public class PersonLookupInfo : ItemLookupInfo - { - - } - - public class MovieInfo : ItemLookupInfo - { - - } - - public class BoxSetInfo : ItemLookupInfo - { - - } - - public class MusicVideoInfo : ItemLookupInfo - { - - } - - public class TrailerInfo : ItemLookupInfo - { - public bool IsLocalTrailer { get; set; } - } - - public class BookInfo : ItemLookupInfo - { - public string SeriesName { get; set; } - } - - public class SeasonInfo : ItemLookupInfo, IHasIdentities - { - private List _identities = new List(); - - public Dictionary SeriesProviderIds { get; set; } - public int? AnimeSeriesIndex { get; set; } - - public SeasonInfo() - { - SeriesProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase); - } - - public IEnumerable Identities - { - get { return _identities; } - } - - public async Task FindIdentities(IProviderManager providerManager, CancellationToken cancellationToken) - { - var identifier = new ItemIdentifier(); - _identities = (await identifier.FindIdentities(this, providerManager, cancellationToken)).ToList(); - } - } - - public class SeasonIdentity : IItemIdentity - { - public string Type { get; set; } - - public string SeriesId { get; set; } - - public int SeasonIndex { get; set; } - } - - public class ChannelItemLookupInfo : ItemLookupInfo - { - public ChannelMediaContentType ContentType { get; set; } - public ExtraType ExtraType { get; set; } - } } diff --git a/MediaBrowser.Controller/Providers/LocalImageInfo.cs b/MediaBrowser.Controller/Providers/LocalImageInfo.cs new file mode 100644 index 000000000..59d74def2 --- /dev/null +++ b/MediaBrowser.Controller/Providers/LocalImageInfo.cs @@ -0,0 +1,11 @@ +using System.IO; +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.Controller.Providers +{ + public class LocalImageInfo + { + public FileSystemInfo FileInfo { get; set; } + public ImageType Type { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/LocalMetadataResult.cs b/MediaBrowser.Controller/Providers/LocalMetadataResult.cs new file mode 100644 index 000000000..8be3ee7aa --- /dev/null +++ b/MediaBrowser.Controller/Providers/LocalMetadataResult.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.Controller.Providers +{ + public class LocalMetadataResult + where T : IHasMetadata + { + public bool HasMetadata { get; set; } + public T Item { get; set; } + + public List Images { get; set; } + public List Chapters { get; set; } + public List UserDataLIst { get; set; } + + public LocalMetadataResult() + { + Images = new List(); + Chapters = new List(); + UserDataLIst = new List(); + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/MetadataRefreshMode.cs b/MediaBrowser.Controller/Providers/MetadataRefreshMode.cs new file mode 100644 index 000000000..56492006a --- /dev/null +++ b/MediaBrowser.Controller/Providers/MetadataRefreshMode.cs @@ -0,0 +1,25 @@ +namespace MediaBrowser.Controller.Providers +{ + public enum MetadataRefreshMode + { + /// + /// The none + /// + None = 0, + + /// + /// The validation only + /// + ValidationOnly = 1, + + /// + /// Providers will be executed based on default rules + /// + Default = 2, + + /// + /// All providers will be executed to search for new metadata + /// + FullRefresh = 3 + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs index 078f1e77a..dbb7fbfcd 100644 --- a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs +++ b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs @@ -1,6 +1,4 @@ -using MediaBrowser.Model.Entities; -using System.Collections.Generic; -using System.Linq; +using System.Linq; namespace MediaBrowser.Controller.Providers { @@ -40,74 +38,4 @@ namespace MediaBrowser.Controller.Providers ReplaceImages = copy.ReplaceImages.ToList(); } } - - public class ImageRefreshOptions - { - public ImageRefreshMode ImageRefreshMode { get; set; } - public IDirectoryService DirectoryService { get; private set; } - - public bool ReplaceAllImages { get; set; } - - public List ReplaceImages { get; set; } - - public ImageRefreshOptions(IDirectoryService directoryService) - { - ImageRefreshMode = ImageRefreshMode.Default; - DirectoryService = directoryService; - - ReplaceImages = new List(); - } - - public bool IsReplacingImage(ImageType type) - { - return ImageRefreshMode == ImageRefreshMode.FullRefresh && - (ReplaceAllImages || ReplaceImages.Contains(type)); - } - } - - public enum MetadataRefreshMode - { - /// - /// The none - /// - None = 0, - - /// - /// The validation only - /// - ValidationOnly = 1, - - /// - /// Providers will be executed based on default rules - /// - Default = 2, - - /// - /// All providers will be executed to search for new metadata - /// - FullRefresh = 3 - } - - public enum ImageRefreshMode - { - /// - /// The none - /// - None = 0, - - /// - /// The default - /// - Default = 1, - - /// - /// Existing images will be validated - /// - ValidationOnly = 2, - - /// - /// All providers will be executed to search for new metadata - /// - FullRefresh = 3 - } } diff --git a/MediaBrowser.Controller/Providers/MetadataResult.cs b/MediaBrowser.Controller/Providers/MetadataResult.cs new file mode 100644 index 000000000..756458cfa --- /dev/null +++ b/MediaBrowser.Controller/Providers/MetadataResult.cs @@ -0,0 +1,8 @@ +namespace MediaBrowser.Controller.Providers +{ + public class MetadataResult + { + public bool HasMetadata { get; set; } + public T Item { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/MovieInfo.cs b/MediaBrowser.Controller/Providers/MovieInfo.cs new file mode 100644 index 000000000..198336fc0 --- /dev/null +++ b/MediaBrowser.Controller/Providers/MovieInfo.cs @@ -0,0 +1,7 @@ +namespace MediaBrowser.Controller.Providers +{ + public class MovieInfo : ItemLookupInfo + { + + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/MusicVideoInfo.cs b/MediaBrowser.Controller/Providers/MusicVideoInfo.cs new file mode 100644 index 000000000..4f4ab5954 --- /dev/null +++ b/MediaBrowser.Controller/Providers/MusicVideoInfo.cs @@ -0,0 +1,7 @@ +namespace MediaBrowser.Controller.Providers +{ + public class MusicVideoInfo : ItemLookupInfo + { + + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/PersonLookupInfo.cs b/MediaBrowser.Controller/Providers/PersonLookupInfo.cs new file mode 100644 index 000000000..db4dacb0b --- /dev/null +++ b/MediaBrowser.Controller/Providers/PersonLookupInfo.cs @@ -0,0 +1,7 @@ +namespace MediaBrowser.Controller.Providers +{ + public class PersonLookupInfo : ItemLookupInfo + { + + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/RemoteSearchQuery.cs b/MediaBrowser.Controller/Providers/RemoteSearchQuery.cs new file mode 100644 index 000000000..cd86f352f --- /dev/null +++ b/MediaBrowser.Controller/Providers/RemoteSearchQuery.cs @@ -0,0 +1,19 @@ +namespace MediaBrowser.Controller.Providers +{ + public class RemoteSearchQuery + where T : ItemLookupInfo + { + public T SearchInfo { get; set; } + + /// + /// If set will only search within the given provider + /// + public string SearchProviderName { get; set; } + + /// + /// Gets or sets a value indicating whether [include disabled providers]. + /// + /// true if [include disabled providers]; otherwise, false. + public bool IncludeDisabledProviders { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/SeasonIdentity.cs b/MediaBrowser.Controller/Providers/SeasonIdentity.cs new file mode 100644 index 000000000..1e6b9b65a --- /dev/null +++ b/MediaBrowser.Controller/Providers/SeasonIdentity.cs @@ -0,0 +1,11 @@ +namespace MediaBrowser.Controller.Providers +{ + public class SeasonIdentity : IItemIdentity + { + public string Type { get; set; } + + public string SeriesId { get; set; } + + public int SeasonIndex { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/SeasonInfo.cs b/MediaBrowser.Controller/Providers/SeasonInfo.cs new file mode 100644 index 000000000..17bcd3f77 --- /dev/null +++ b/MediaBrowser.Controller/Providers/SeasonInfo.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Providers +{ + public class SeasonInfo : ItemLookupInfo, IHasIdentities + { + private List _identities = new List(); + + public Dictionary SeriesProviderIds { get; set; } + public int? AnimeSeriesIndex { get; set; } + + public SeasonInfo() + { + SeriesProviderIds = new Dictionary(StringComparer.OrdinalIgnoreCase); + } + + public IEnumerable Identities + { + get { return _identities; } + } + + public async Task FindIdentities(IProviderManager providerManager, CancellationToken cancellationToken) + { + var identifier = new ItemIdentifier(); + _identities = (await identifier.FindIdentities(this, providerManager, cancellationToken)).ToList(); + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/SeriesIdentity.cs b/MediaBrowser.Controller/Providers/SeriesIdentity.cs new file mode 100644 index 000000000..326d34027 --- /dev/null +++ b/MediaBrowser.Controller/Providers/SeriesIdentity.cs @@ -0,0 +1,9 @@ +namespace MediaBrowser.Controller.Providers +{ + public class SeriesIdentity : IItemIdentity + { + public string Type { get; set; } + + public string Id { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/SeriesInfo.cs b/MediaBrowser.Controller/Providers/SeriesInfo.cs new file mode 100644 index 000000000..fc1119cd2 --- /dev/null +++ b/MediaBrowser.Controller/Providers/SeriesInfo.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Providers +{ + public class SeriesInfo : ItemLookupInfo, IHasIdentities + { + private List _identities = new List(); + + public int? AnimeSeriesIndex { get; set; } + + public IEnumerable Identities + { + get { return _identities; } + } + + public async Task FindIdentities(IProviderManager providerManager, CancellationToken cancellationToken) + { + var identifier = new ItemIdentifier(); + _identities = (await identifier.FindIdentities(this, providerManager, cancellationToken)).ToList(); + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/SeriesOrderTypes.cs b/MediaBrowser.Controller/Providers/SeriesOrderTypes.cs new file mode 100644 index 000000000..5e04fb4db --- /dev/null +++ b/MediaBrowser.Controller/Providers/SeriesOrderTypes.cs @@ -0,0 +1,7 @@ +namespace MediaBrowser.Controller.Providers +{ + public static class SeriesOrderTypes + { + public const string Anime = "Anime"; + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/SongInfo.cs b/MediaBrowser.Controller/Providers/SongInfo.cs new file mode 100644 index 000000000..b83912a00 --- /dev/null +++ b/MediaBrowser.Controller/Providers/SongInfo.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; + +namespace MediaBrowser.Controller.Providers +{ + public class SongInfo : ItemLookupInfo + { + public List AlbumArtists { get; set; } + public string Album { get; set; } + public List Artists { get; set; } + + public SongInfo() + { + Artists = new List(); + AlbumArtists = new List(); + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Providers/TrailerInfo.cs b/MediaBrowser.Controller/Providers/TrailerInfo.cs new file mode 100644 index 000000000..fe26ec43e --- /dev/null +++ b/MediaBrowser.Controller/Providers/TrailerInfo.cs @@ -0,0 +1,7 @@ +namespace MediaBrowser.Controller.Providers +{ + public class TrailerInfo : ItemLookupInfo + { + public bool IsLocalTrailer { get; set; } + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Sync/IServerSyncProvider.cs b/MediaBrowser.Controller/Sync/IServerSyncProvider.cs index 98ea2ce06..422349b80 100644 --- a/MediaBrowser.Controller/Sync/IServerSyncProvider.cs +++ b/MediaBrowser.Controller/Sync/IServerSyncProvider.cs @@ -18,7 +18,7 @@ namespace MediaBrowser.Controller.Sync /// The progress. /// The cancellation token. /// Task. - Task SendFile(Stream stream, string remotePath, SyncTarget target, IProgress progress, CancellationToken cancellationToken); + Task SendFile(Stream stream, string remotePath, SyncTarget target, IProgress progress, CancellationToken cancellationToken); /// /// Deletes the file. diff --git a/MediaBrowser.Controller/Sync/SendFileResult.cs b/MediaBrowser.Controller/Sync/SendFileResult.cs new file mode 100644 index 000000000..62753444a --- /dev/null +++ b/MediaBrowser.Controller/Sync/SendFileResult.cs @@ -0,0 +1,18 @@ +using MediaBrowser.Model.MediaInfo; + +namespace MediaBrowser.Controller.Sync +{ + public class SendFileResult + { + /// + /// Gets or sets the path. + /// + /// The path. + public string Path { get; set; } + /// + /// Gets or sets the protocol. + /// + /// The protocol. + public MediaProtocol Protocol { get; set; } + } +} diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj index 2e61ed89c..74f927c7e 100644 --- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj +++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj @@ -491,6 +491,9 @@ Dto\MetadataEditorInfo.cs + + Dto\NameIdPair.cs + Dto\NameValuePair.cs @@ -977,9 +980,6 @@ Querying\SessionQuery.cs - - Querying\SimilarItemsByNameQuery.cs - Querying\SimilarItemsQuery.cs diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj index ba4ac22e7..7f6f7bc13 100644 --- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj +++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj @@ -459,6 +459,9 @@ Dto\MetadataEditorInfo.cs + + Dto\NameIdPair.cs + Dto\NameValuePair.cs @@ -939,9 +942,6 @@ Querying\SessionQuery.cs - - Querying\SimilarItemsByNameQuery.cs - Querying\SimilarItemsQuery.cs diff --git a/MediaBrowser.Model/ApiClient/IApiClient.cs b/MediaBrowser.Model/ApiClient/IApiClient.cs index 190f2100e..7e07b3f3b 100644 --- a/MediaBrowser.Model/ApiClient/IApiClient.cs +++ b/MediaBrowser.Model/ApiClient/IApiClient.cs @@ -251,12 +251,12 @@ namespace MediaBrowser.Model.ApiClient Task GetAdditionalParts(string itemId, string userId); /// - /// Gets the live media information. + /// Gets the playback information. /// /// The item identifier. /// The user identifier. /// Task<LiveMediaInfoResult>. - Task GetLiveMediaInfo(string itemId, string userId); + Task GetPlaybackInfo(string itemId, string userId); /// /// Gets the users async. @@ -344,14 +344,14 @@ namespace MediaBrowser.Model.ApiClient /// /// The query. /// Task{ItemsResult}. - Task GetInstantMixFromArtistAsync(SimilarItemsByNameQuery query); + Task GetInstantMixFromArtistAsync(SimilarItemsQuery query); /// /// Gets the instant mix from music genre async. /// /// The query. /// Task{ItemsResult}. - Task GetInstantMixFromMusicGenreAsync(SimilarItemsByNameQuery query); + Task GetInstantMixFromMusicGenreAsync(SimilarItemsQuery query); /// /// Gets the similar movies async. @@ -417,15 +417,6 @@ namespace MediaBrowser.Model.ApiClient /// Task{ItemsResult}. Task GetAlbumArtistsAsync(ArtistsQuery query); - /// - /// Gets a studio - /// - /// The name. - /// The user id. - /// Task{BaseItemDto}. - /// userId - Task GetStudioAsync(string name, string userId); - /// /// Gets the next up async. /// @@ -494,15 +485,6 @@ namespace MediaBrowser.Model.ApiClient /// Task{BaseItemDto}. Task GetGameGenreAsync(string name, string userId); - /// - /// Gets the artist async. - /// - /// The name. - /// The user id. - /// Task{BaseItemDto}. - /// name - Task GetArtistAsync(string name, string userId); - /// /// Restarts the server. /// @@ -1011,14 +993,6 @@ namespace MediaBrowser.Model.ApiClient /// item string GetPersonImageUrl(BaseItemPerson item, ImageOptions options); - /// - /// Gets an image url that can be used to download an image from the api - /// - /// The year. - /// The options. - /// System.String. - string GetYearImageUrl(int year, ImageOptions options); - /// /// Gets an image url that can be used to download an image from the api /// @@ -1044,24 +1018,6 @@ namespace MediaBrowser.Model.ApiClient /// System.String. string GetGameGenreImageUrl(string name, ImageOptions options); - /// - /// Gets an image url that can be used to download an image from the api - /// - /// The name. - /// The options. - /// System.String. - /// name - string GetStudioImageUrl(string name, ImageOptions options); - - /// - /// Gets the artist image URL. - /// - /// The name. - /// The options. - /// System.String. - /// name - string GetArtistImageUrl(string name, ImageOptions options); - /// /// This is a helper to get a list of backdrop url's from a given ApiBaseItemWrapper. If the actual item does not have any backdrops it will return backdrops from the first parent that does. /// diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index bb57e9d47..c06aedb50 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -44,6 +44,12 @@ namespace MediaBrowser.Model.Configuration /// true if [use HTTPS]; otherwise, false. public bool EnableHttps { get; set; } + /// + /// Gets or sets a value indicating whether [enable user specific user views]. + /// + /// true if [enable user specific user views]; otherwise, false. + public bool EnableUserSpecificUserViews { get; set; } + /// /// Gets or sets the value pointing to the file system where the ssl certiifcate is located.. /// diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 113a4c6f4..7a1c78112 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -466,6 +466,12 @@ namespace MediaBrowser.Model.Dto /// The artists. public List Artists { get; set; } + /// + /// Gets or sets the artist items. + /// + /// The artist items. + public List ArtistItems { get; set; } + /// /// Gets or sets the album. /// @@ -507,6 +513,12 @@ namespace MediaBrowser.Model.Dto /// The album artist. public string AlbumArtist { get; set; } + /// + /// Gets or sets the album artists. + /// + /// The album artists. + public List AlbumArtists { get; set; } + /// /// Gets or sets the name of the season. /// diff --git a/MediaBrowser.Model/Dto/NameIdPair.cs b/MediaBrowser.Model/Dto/NameIdPair.cs new file mode 100644 index 000000000..d3931516c --- /dev/null +++ b/MediaBrowser.Model/Dto/NameIdPair.cs @@ -0,0 +1,17 @@ + +namespace MediaBrowser.Model.Dto +{ + public class NameIdPair + { + /// + /// Gets or sets the name. + /// + /// The name. + public string Name { get; set; } + /// + /// Gets or sets the identifier. + /// + /// The identifier. + public string Id { get; set; } + } +} diff --git a/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs b/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs index a6cd85d8d..d6d698038 100644 --- a/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs +++ b/MediaBrowser.Model/LiveTv/RecordingInfoDto.cs @@ -273,6 +273,10 @@ namespace MediaBrowser.Model.LiveTv /// The type. public string Type { get; set; } + /// + /// Gets or sets the media sources. + /// + /// The media sources. public List MediaSources { get; set; } public RecordingInfoDto() diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 14ec093ec..601ba6dc1 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -139,6 +139,7 @@ + @@ -321,7 +322,6 @@ - diff --git a/MediaBrowser.Model/Querying/ItemQuery.cs b/MediaBrowser.Model/Querying/ItemQuery.cs index 0f929fa9b..6d26a2c0a 100644 --- a/MediaBrowser.Model/Querying/ItemQuery.cs +++ b/MediaBrowser.Model/Querying/ItemQuery.cs @@ -39,11 +39,11 @@ namespace MediaBrowser.Model.Querying public string[] SortBy { get; set; } /// - /// Filter by artists + /// Gets or sets the artist ids. /// - /// The artists. - public string[] Artists { get; set; } - + /// The artist ids. + public string[] ArtistIds { get; set; } + /// /// The sort order to return results with /// @@ -93,16 +93,10 @@ namespace MediaBrowser.Model.Querying public string[] Genres { get; set; } /// - /// Limit results to items containing specific genres + /// Gets or sets the studio ids. /// - /// The genres. - public string[] AllGenres { get; set; } - - /// - /// Limit results to items containing specific studios - /// - /// The studios. - public string[] Studios { get; set; } + /// The studio ids. + public string[] StudioIds { get; set; } /// /// Gets or sets the exclude item types. @@ -306,13 +300,13 @@ namespace MediaBrowser.Model.Querying VideoTypes = new VideoType[] { }; Genres = new string[] { }; - Studios = new string[] { }; + StudioIds = new string[] { }; IncludeItemTypes = new string[] { }; ExcludeItemTypes = new string[] { }; Years = new int[] { }; PersonTypes = new string[] { }; Ids = new string[] { }; - Artists = new string[] { }; + ArtistIds = new string[] { }; ImageTypes = new ImageType[] { }; AirDays = new DayOfWeek[] { }; diff --git a/MediaBrowser.Model/Querying/SimilarItemsByNameQuery.cs b/MediaBrowser.Model/Querying/SimilarItemsByNameQuery.cs deleted file mode 100644 index 7d0d4da31..000000000 --- a/MediaBrowser.Model/Querying/SimilarItemsByNameQuery.cs +++ /dev/null @@ -1,29 +0,0 @@ -namespace MediaBrowser.Model.Querying -{ - public class SimilarItemsByNameQuery - { - /// - /// The user to localize search results for - /// - /// The user id. - public string UserId { get; set; } - - /// - /// Gets or sets the name. - /// - /// The name. - public string Name { get; set; } - - /// - /// The maximum number of items to return - /// - /// The limit. - public int? Limit { get; set; } - - /// - /// Fields to return within the items, in addition to basic information - /// - /// The fields. - public ItemFields[] Fields { get; set; } - } -} \ No newline at end of file diff --git a/MediaBrowser.Providers/FolderImages/DefaultImageProvider.cs b/MediaBrowser.Providers/FolderImages/DefaultImageProvider.cs index 8ddbbba7d..73a1de889 100644 --- a/MediaBrowser.Providers/FolderImages/DefaultImageProvider.cs +++ b/MediaBrowser.Providers/FolderImages/DefaultImageProvider.cs @@ -12,7 +12,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Providers.FolderImages { - public class DefaultImageProvider : IRemoteImageProvider, IHasItemChangeMonitor + public class DefaultImageProvider : IRemoteImageProvider, IHasItemChangeMonitor, IHasOrder { private readonly IHttpClient _httpClient; @@ -36,36 +36,42 @@ namespace MediaBrowser.Providers.FolderImages if (view != null) { - return GetImages(view.ViewType, cancellationToken); + return GetImages(view.ViewType, view.ParentId != Guid.Empty, cancellationToken); } var folder = (ICollectionFolder)item; - return GetImages(folder.CollectionType, cancellationToken); + return GetImages(folder.CollectionType, false, cancellationToken); } - private Task> GetImages(string viewType, CancellationToken cancellationToken) + private Task> GetImages(string viewType, bool isSubView, CancellationToken cancellationToken) { - var url = GetImageUrl(viewType); + var url = GetImageUrl(viewType, isSubView); + var list = new List(); - return Task.FromResult>(new List + if (!string.IsNullOrWhiteSpace(url)) { - new RemoteImageInfo - { - ProviderName = Name, - Url = url, - Type = ImageType.Primary - }, + list.AddRange(new List + { + new RemoteImageInfo + { + ProviderName = Name, + Url = url, + Type = ImageType.Primary + }, - new RemoteImageInfo - { - ProviderName = Name, - Url = url, - Type = ImageType.Thumb - } - }); + new RemoteImageInfo + { + ProviderName = Name, + Url = url, + Type = ImageType.Thumb + } + }); + } + + return Task.FromResult>(list); } - private string GetImageUrl(string viewType) + private string GetImageUrl(string viewType, bool isSubView) { const string urlPrefix = "https://raw.githubusercontent.com/MediaBrowser/MediaBrowser.Resources/master/images/folders/"; @@ -102,6 +108,11 @@ namespace MediaBrowser.Providers.FolderImages return urlPrefix + "movies.png"; } + if (isSubView) + { + return null; + } + return urlPrefix + "generic.png"; } @@ -112,14 +123,7 @@ namespace MediaBrowser.Providers.FolderImages public bool Supports(IHasImages item) { - var view = item as UserView; - - if (view != null) - { - return !view.UserId.HasValue; - } - - return item is ICollectionFolder; + return item is ICollectionFolder || item is UserView; } public Task GetImageResponse(string url, CancellationToken cancellationToken) @@ -136,5 +140,14 @@ namespace MediaBrowser.Providers.FolderImages { return GetSupportedImages(item).Any(i => !item.HasImage(i)); } + + public int Order + { + get + { + // Run after the dynamic image provider + return 1; + } + } } } diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index 66b0f9259..3c75aa20a 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -135,17 +135,17 @@ namespace MediaBrowser.Providers.Manager { if (!string.IsNullOrEmpty(response.Path)) { - var mimeType = "image/" + Path.GetExtension(response.Path).TrimStart('.').ToLower(); + var mimeType = MimeTypes.GetMimeType(response.Path); var stream = _fileSystem.GetFileStream(response.Path, FileMode.Open, FileAccess.Read, FileShare.Read, true); - await _providerManager.SaveImage(item, stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false); + await _providerManager.SaveImage(item, stream, mimeType, imageType, null, response.InternalCacheKey, cancellationToken).ConfigureAwait(false); } else { var mimeType = "image/" + response.Format.ToString().ToLower(); - await _providerManager.SaveImage(item, response.Stream, mimeType, imageType, null, cancellationToken).ConfigureAwait(false); + await _providerManager.SaveImage(item, response.Stream, mimeType, imageType, null, response.InternalCacheKey, cancellationToken).ConfigureAwait(false); } downloadedImages.Add(imageType); diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs index 55a454977..392fcd5ae 100644 --- a/MediaBrowser.Providers/Manager/ProviderManager.cs +++ b/MediaBrowser.Providers/Manager/ProviderManager.cs @@ -26,7 +26,7 @@ namespace MediaBrowser.Providers.Manager /// /// Class ProviderManager /// - public class ProviderManager : IProviderManager + public class ProviderManager : IProviderManager, IDisposable { /// /// The _logger @@ -63,6 +63,8 @@ namespace MediaBrowser.Providers.Manager private IExternalId[] _externalIds; + private readonly Func _libraryManagerFactory; + /// /// Initializes a new instance of the class. /// @@ -71,7 +73,7 @@ namespace MediaBrowser.Providers.Manager /// The directory watchers. /// The log manager. /// The file system. - public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILogManager logManager, IFileSystem fileSystem, IServerApplicationPaths appPaths) + public ProviderManager(IHttpClient httpClient, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILogManager logManager, IFileSystem fileSystem, IServerApplicationPaths appPaths, Func libraryManagerFactory) { _logger = logManager.GetLogger("ProviderManager"); _httpClient = httpClient; @@ -79,6 +81,7 @@ namespace MediaBrowser.Providers.Manager _libraryMonitor = libraryMonitor; _fileSystem = fileSystem; _appPaths = appPaths; + _libraryManagerFactory = libraryManagerFactory; } /// @@ -841,5 +844,80 @@ namespace MediaBrowser.Providers.Manager }); } + + private readonly ConcurrentQueue> _refreshQueue = + new ConcurrentQueue>(); + + private readonly object _refreshTimerLock = new object(); + private Timer _refreshTimer; + + public void QueueRefresh(Guid id, MetadataRefreshOptions options) + { + if (_disposed) + { + return; + } + + _refreshQueue.Enqueue(new Tuple(id, options)); + StartRefreshTimer(); + } + + private void StartRefreshTimer() + { + lock (_refreshTimerLock) + { + if (_refreshTimer == null) + { + _refreshTimer = new Timer(RefreshTimerCallback, null, 100, Timeout.Infinite); + } + } + } + + private void StopRefreshTimer() + { + lock (_refreshTimerLock) + { + if (_refreshTimer != null) + { + _refreshTimer.Dispose(); + _refreshTimer = null; + } + } + } + + private async void RefreshTimerCallback(object state) + { + Tuple refreshItem; + var libraryManager = _libraryManagerFactory(); + + while (_refreshQueue.TryDequeue(out refreshItem)) + { + if (_disposed) + { + return; + } + + try + { + var item = libraryManager.GetItemById(refreshItem.Item1); + if (item != null) + { + await item.RefreshMetadata(refreshItem.Item2, CancellationToken.None).ConfigureAwait(false); + } + } + catch (Exception ex) + { + _logger.ErrorException("Error refreshing item", ex); + } + } + + StopRefreshTimer(); + } + + private bool _disposed; + public void Dispose() + { + _disposed = true; + } } } \ No newline at end of file diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs index 26d00d544..ea191dd08 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs @@ -387,7 +387,7 @@ namespace MediaBrowser.Providers.MediaInfo if (!string.IsNullOrEmpty(val)) { // Sometimes the artist name is listed here, account for that - var studios = Split(val, true).Where(i => !audio.HasArtist(i)); + var studios = Split(val, true).Where(i => !audio.HasAnyArtist(i)); foreach (var studio in studios) { diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs index 2b17442de..f0f30229e 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs @@ -1400,7 +1400,9 @@ namespace MediaBrowser.Server.Implementations.Channels public async Task GetInternalChannelFolder(string userId, CancellationToken cancellationToken) { var name = _localization.GetLocalizedString("ViewTypeChannels"); - return await _libraryManager.GetNamedView(name, "channels", "zz_" + name, cancellationToken).ConfigureAwait(false); + var user = _userManager.GetUserById(userId); + + return await _libraryManager.GetNamedView(user, name, "channels", "zz_" + name, cancellationToken).ConfigureAwait(false); } public async Task DownloadChannelItem(IChannelMediaItem item, string destination, diff --git a/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs b/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs index b756fb6c4..80a7c50d1 100644 --- a/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs +++ b/MediaBrowser.Server.Implementations/Collections/CollectionImageProvider.cs @@ -14,7 +14,7 @@ using System.Threading.Tasks; namespace MediaBrowser.Server.Implementations.Collections { - public class CollectionImageProvider : BaseDynamicImageProvider, ICustomMetadataProvider + public class CollectionImageProvider : BaseDynamicImageProvider { public CollectionImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths) : base(fileSystem, providerManager, applicationPaths) { diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index f9b7470b2..3280cf264 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -504,7 +504,6 @@ namespace MediaBrowser.Server.Implementations.Dto } dto.Album = item.Album; - dto.Artists = item.Artists; } private void SetGameProperties(BaseItemDto dto, Game item) @@ -1142,7 +1141,6 @@ namespace MediaBrowser.Server.Implementations.Dto if (audio != null) { dto.Album = audio.Album; - dto.Artists = audio.Artists; var albumParent = audio.FindParent(); @@ -1163,18 +1161,65 @@ namespace MediaBrowser.Server.Implementations.Dto if (album != null) { - dto.Artists = album.Artists; - dto.SoundtrackIds = album.SoundtrackIds .Select(i => i.ToString("N")) .ToArray(); } - var hasAlbumArtist = item as IHasAlbumArtist; + var hasArtist = item as IHasArtist; + if (hasArtist != null) + { + dto.Artists = hasArtist.Artists; + dto.ArtistItems = hasArtist + .Artists + .Select(i => + { + try + { + var artist = _libraryManager.GetArtist(i); + return new NameIdPair + { + Name = artist.Name, + Id = artist.Id.ToString("N") + }; + } + catch (Exception ex) + { + _logger.ErrorException("Error getting artist", ex); + return null; + } + }) + .Where(i => i != null) + .ToList(); + } + + var hasAlbumArtist = item as IHasAlbumArtist; if (hasAlbumArtist != null) { dto.AlbumArtist = hasAlbumArtist.AlbumArtists.FirstOrDefault(); + + dto.AlbumArtists = hasAlbumArtist + .AlbumArtists + .Select(i => + { + try + { + var artist = _libraryManager.GetArtist(i); + return new NameIdPair + { + Name = artist.Name, + Id = artist.Id.ToString("N") + }; + } + catch (Exception ex) + { + _logger.ErrorException("Error getting album artist", ex); + return null; + } + }) + .Where(i => i != null) + .ToList(); } // Add video info @@ -1231,7 +1276,6 @@ namespace MediaBrowser.Server.Implementations.Dto // Add MovieInfo var movie = item as Movie; - if (movie != null) { if (fields.Contains(ItemFields.TmdbCollectionName)) @@ -1241,7 +1285,6 @@ namespace MediaBrowser.Server.Implementations.Dto } var hasSpecialFeatures = item as IHasSpecialFeatures; - if (hasSpecialFeatures != null) { var specialFeatureCount = hasSpecialFeatures.SpecialFeatureIds.Count; @@ -1254,7 +1297,6 @@ namespace MediaBrowser.Server.Implementations.Dto // Add EpisodeInfo var episode = item as Episode; - if (episode != null) { dto.IndexNumberEnd = episode.IndexNumberEnd; @@ -1296,7 +1338,6 @@ namespace MediaBrowser.Server.Implementations.Dto // Add SeriesInfo var series = item as Series; - if (series != null) { dto.AirDays = series.AirDays; @@ -1346,7 +1387,6 @@ namespace MediaBrowser.Server.Implementations.Dto // Add SeasonInfo var season = item as Season; - if (season != null) { series = season.Series; @@ -1380,7 +1420,6 @@ namespace MediaBrowser.Server.Implementations.Dto } var musicVideo = item as MusicVideo; - if (musicVideo != null) { SetMusicVideoProperties(dto, musicVideo); diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 070b111ee..f6809c924 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -1584,15 +1584,22 @@ namespace MediaBrowser.Server.Implementations.Library .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); } - public async Task GetNamedView(string name, - string type, + public async Task GetNamedView(User user, + string name, + string viewType, string sortName, CancellationToken cancellationToken) { + if (ConfigurationManager.Configuration.EnableUserSpecificUserViews) + { + return await GetNamedViewInternal(user, name, null, viewType, sortName, cancellationToken) + .ConfigureAwait(false); + } + var path = Path.Combine(ConfigurationManager.ApplicationPaths.ItemsByNamePath, "views"); - path = Path.Combine(path, _fileSystem.GetValidFilename(type)); + path = Path.Combine(path, _fileSystem.GetValidFilename(viewType)); var id = GetNewItemId(path + "_namedview_" + name, typeof(UserView)); @@ -1611,7 +1618,7 @@ namespace MediaBrowser.Server.Implementations.Library Id = id, DateCreated = DateTime.UtcNow, Name = name, - ViewType = type, + ViewType = viewType, ForcedSortName = sortName }; @@ -1627,17 +1634,29 @@ namespace MediaBrowser.Server.Implementations.Library if (refresh) { - await item.RefreshMetadata(new MetadataRefreshOptions - { - ForceSave = true - - }, cancellationToken).ConfigureAwait(false); + await item.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None).ConfigureAwait(false); + _providerManagerFactory().QueueRefresh(item.Id, new MetadataRefreshOptions()); } return item; } - public async Task GetSpecialFolder(User user, + public Task GetNamedView(User user, + string name, + string parentId, + string viewType, + string sortName, + CancellationToken cancellationToken) + { + if (string.IsNullOrWhiteSpace(parentId)) + { + throw new ArgumentNullException("parentId"); + } + + return GetNamedViewInternal(user, name, parentId, viewType, sortName, cancellationToken); + } + + private async Task GetNamedViewInternal(User user, string name, string parentId, string viewType, @@ -1649,19 +1668,14 @@ namespace MediaBrowser.Server.Implementations.Library throw new ArgumentNullException("name"); } - if (string.IsNullOrWhiteSpace(parentId)) - { - throw new ArgumentNullException("parentId"); - } - if (string.IsNullOrWhiteSpace(viewType)) { throw new ArgumentNullException("viewType"); } - var id = GetNewItemId("7_namedview_" + name + user.Id.ToString("N") + parentId, typeof(UserView)); + var id = GetNewItemId("23_namedview_" + name + user.Id.ToString("N") + (parentId ?? string.Empty), typeof(UserView)); - var path = Path.Combine(ConfigurationManager.ApplicationPaths.InternalMetadataPath, "views", "specialviews", id.ToString("N")); + var path = Path.Combine(ConfigurationManager.ApplicationPaths.InternalMetadataPath, "views", id.ToString("N")); var item = GetItemById(id) as UserView; @@ -1679,27 +1693,28 @@ namespace MediaBrowser.Server.Implementations.Library Name = name, ViewType = viewType, ForcedSortName = sortName, - UserId = user.Id, - ParentId = new Guid(parentId) + UserId = user.Id }; + if (!string.IsNullOrWhiteSpace(parentId)) + { + item.ParentId = new Guid(parentId); + } + await CreateItem(item, cancellationToken).ConfigureAwait(false); refresh = true; } - if (!refresh && item != null) + if (!refresh) { refresh = (DateTime.UtcNow - item.DateLastSaved).TotalHours >= 24; } if (refresh) { - await item.RefreshMetadata(new MetadataRefreshOptions - { - ForceSave = true - - }, cancellationToken).ConfigureAwait(false); + await item.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None).ConfigureAwait(false); + _providerManagerFactory().QueueRefresh(item.Id, new MetadataRefreshOptions()); } return item; @@ -1849,7 +1864,7 @@ namespace MediaBrowser.Server.Implementations.Library // These cause apps to have problems options.AudioFileExtensions.Remove(".m3u"); options.AudioFileExtensions.Remove(".wpl"); - + if (!ConfigurationManager.Configuration.EnableAudioArchiveFiles) { options.AudioFileExtensions.Remove(".rar"); diff --git a/MediaBrowser.Server.Implementations/Library/MusicManager.cs b/MediaBrowser.Server.Implementations/Library/MusicManager.cs index 7733e7d37..3a854f2fe 100644 --- a/MediaBrowser.Server.Implementations/Library/MusicManager.cs +++ b/MediaBrowser.Server.Implementations/Library/MusicManager.cs @@ -34,7 +34,7 @@ namespace MediaBrowser.Server.Implementations.Library var genres = user.RootFolder .GetRecursiveChildren(user, i => i is Audio) .Cast