diff --git a/MediaBrowser.Api/TvShowsService.cs b/MediaBrowser.Api/TvShowsService.cs index ad2df9bce..e3dfb7f5a 100644 --- a/MediaBrowser.Api/TvShowsService.cs +++ b/MediaBrowser.Api/TvShowsService.cs @@ -429,7 +429,7 @@ namespace MediaBrowser.Api if (request.IsMissing.HasValue) { var val = request.IsMissing.Value; - items = items.Where(i => i.IsMissingSeason == val); + items = items.Where(i => (i.IsMissingSeason ?? false) == val); } if (request.IsVirtualUnaired.HasValue) diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 1c8817afe..61060766f 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -149,6 +149,12 @@ namespace MediaBrowser.Controller.Entities } } + [IgnoreDataMember] + public bool IsUnaired + { + get { return PremiereDate.HasValue && PremiereDate.Value.ToLocalTime().Date >= DateTime.Now.Date; } + } + public string OriginalTitle { get; set; } /// diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 79cbd7bd3..77e362419 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -1316,7 +1316,8 @@ namespace MediaBrowser.Controller.Entities { var folder = (Folder)child; - folder.AddChildrenToList(result, includeLinkedChildren, true, filter); + // We can only support includeLinkedChildren for the first folder, or we might end up stuck in a loop of linked items + folder.AddChildrenToList(result, false, true, filter); } } diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index 605b838cd..a4b0b3082 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -210,12 +210,6 @@ namespace MediaBrowser.Controller.Entities.TV } } - [IgnoreDataMember] - public bool IsUnaired - { - get { return PremiereDate.HasValue && PremiereDate.Value.ToLocalTime().Date >= DateTime.Now.Date; } - } - [IgnoreDataMember] public bool IsVirtualUnaired { diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index ac8cc0ee2..ab125eecb 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -54,8 +54,8 @@ namespace MediaBrowser.Controller.Entities.TV // Genre, Rating and Stuido will all be the same protected override IEnumerable GetIndexByOptions() { - return new List { - {"None"}, + return new List { + {"None"}, {"Performer"}, {"Director"}, {"Year"}, @@ -128,22 +128,23 @@ namespace MediaBrowser.Controller.Entities.TV return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name; } - [IgnoreDataMember] - public bool IsMissingSeason + public override bool RequiresRefresh() { - get { return LocationType == LocationType.Virtual && GetEpisodes().All(i => i.IsMissingEpisode); } - } + var result = base.RequiresRefresh(); - private bool GetIsUnaired() - { - return GetEpisodes().All(i => i.IsUnaired); + if (!result) + { + if (!IsMissingSeason.HasValue) + { + return true; + } + } + + return result; } [IgnoreDataMember] - public bool IsUnaired - { - get { return GetIsUnaired(); } - } + public bool? IsMissingSeason { get; set; } [IgnoreDataMember] public bool IsVirtualUnaired @@ -154,7 +155,7 @@ namespace MediaBrowser.Controller.Entities.TV [IgnoreDataMember] public bool IsMissingOrVirtualUnaired { - get { return LocationType == LocationType.Virtual && GetEpisodes().All(i => i.IsVirtualUnaired || i.IsMissingEpisode); } + get { return (IsMissingSeason ?? false) || (LocationType == LocationType.Virtual && IsUnaired); } } [IgnoreDataMember] @@ -223,7 +224,7 @@ namespace MediaBrowser.Controller.Entities.TV episodes = list.DistinctBy(i => i.Id); } - + if (!includeMissingEpisodes) { episodes = episodes.Where(i => !i.IsMissingEpisode); @@ -238,7 +239,7 @@ namespace MediaBrowser.Controller.Entities.TV .Cast(); } - private IEnumerable GetEpisodes() + public IEnumerable GetEpisodes() { var episodes = GetRecursiveChildren().OfType(); var series = Series; diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index f8cdab8ce..54b11a904 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -201,23 +201,30 @@ namespace MediaBrowser.Controller.Entities.TV public IEnumerable GetSeasons(User user, bool includeMissingSeasons, bool includeVirtualUnaired) { - var seriesIds = LibraryManager.GetItemIds(new InternalItemsQuery(user) - { - PresentationUniqueKey = PresentationUniqueKey, - IncludeItemTypes = new[] { typeof(Series).Name } - }); - IEnumerable seasons; - if (seriesIds.Count > 1) + if (EnablePooling()) { - seasons = LibraryManager.GetItemList(new InternalItemsQuery(user) + var seriesIds = LibraryManager.GetItemIds(new InternalItemsQuery(user) { - AncestorIds = seriesIds.Select(i => i.ToString("N")).ToArray(), - IncludeItemTypes = new[] { typeof(Season).Name }, - SortBy = new[] { ItemSortBy.SortName } + PresentationUniqueKey = PresentationUniqueKey, + IncludeItemTypes = new[] { typeof(Series).Name } + }); - }).Cast(); + if (seriesIds.Count > 1) + { + seasons = LibraryManager.GetItemList(new InternalItemsQuery(user) + { + AncestorIds = seriesIds.Select(i => i.ToString("N")).ToArray(), + IncludeItemTypes = new[] { typeof(Season).Name }, + SortBy = new[] { ItemSortBy.SortName } + + }).Cast(); + } + else + { + seasons = LibraryManager.Sort(base.GetChildren(user, true), user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).OfType(); + } } else { @@ -232,7 +239,7 @@ namespace MediaBrowser.Controller.Entities.TV { if (!includeMissingSeasons) { - seasons = seasons.Where(i => !i.IsMissingSeason); + seasons = seasons.Where(i => !(i.IsMissingSeason ?? false)); } if (!includeVirtualUnaired) { @@ -338,25 +345,38 @@ namespace MediaBrowser.Controller.Entities.TV return GetEpisodes(user, seasonNumber, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes); } + private bool EnablePooling() + { + return false; + } + public IEnumerable GetEpisodes(User user, int seasonNumber, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes) { - var seriesIds = LibraryManager.GetItemIds(new InternalItemsQuery(user) - { - PresentationUniqueKey = PresentationUniqueKey, - IncludeItemTypes = new[] { typeof(Series).Name } - }); - IEnumerable episodes; - if (seriesIds.Count > 1) + if (EnablePooling()) { - episodes = LibraryManager.GetItemList(new InternalItemsQuery(user) + var seriesIds = LibraryManager.GetItemIds(new InternalItemsQuery(user) { - AncestorIds = seriesIds.Select(i => i.ToString("N")).ToArray(), - IncludeItemTypes = new[] { typeof(Episode).Name }, - SortBy = new[] { ItemSortBy.SortName } + PresentationUniqueKey = PresentationUniqueKey, + IncludeItemTypes = new[] { typeof(Series).Name } + }); - }).Cast(); + if (seriesIds.Count > 1) + { + episodes = LibraryManager.GetItemList(new InternalItemsQuery(user) + { + AncestorIds = seriesIds.Select(i => i.ToString("N")).ToArray(), + IncludeItemTypes = new[] { typeof(Episode).Name }, + SortBy = new[] { ItemSortBy.SortName } + + }).Cast(); + } + else + { + episodes = GetRecursiveChildren(user, i => i is Episode) + .Cast(); + } } else { diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index 5a0e0b614..ba496fa5c 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -1077,7 +1077,7 @@ namespace MediaBrowser.Controller.Entities var e = i as Season; if (e != null) { - return e.IsMissingSeason == val; + return (e.IsMissingSeason ?? false) == val; } return true; }); diff --git a/MediaBrowser.Controller/Library/IUserDataManager.cs b/MediaBrowser.Controller/Library/IUserDataManager.cs index 4ff0f6439..e2358650b 100644 --- a/MediaBrowser.Controller/Library/IUserDataManager.cs +++ b/MediaBrowser.Controller/Library/IUserDataManager.cs @@ -29,22 +29,6 @@ namespace MediaBrowser.Controller.Library /// Task. Task SaveUserData(Guid userId, IHasUserData item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken); - /// - /// Gets the user data. - /// - /// The user id. - /// The key. - /// Task{UserItemData}. - UserItemData GetUserData(string userId, string key); - - /// - /// Gets the user data. - /// - /// The user id. - /// The key. - /// Task{UserItemData}. - UserItemData GetUserData(Guid userId, string key); - UserItemData GetUserData(IHasUserData user, IHasUserData item); UserItemData GetUserData(string userId, IHasUserData item); diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs index 003cbcfcd..67b1d479b 100644 --- a/MediaBrowser.Controller/Playlists/Playlist.cs +++ b/MediaBrowser.Controller/Playlists/Playlist.cs @@ -142,7 +142,8 @@ namespace MediaBrowser.Controller.Playlists Recursive = true, IsFolder = false, SortBy = new[] { ItemSortBy.SortName }, - MediaTypes = new[] { mediaType } + MediaTypes = new[] { mediaType }, + EnableTotalRecordCount = false }; var itemsResult = await folder.GetItems(query).ConfigureAwait(false); diff --git a/MediaBrowser.Dlna/Profiles/BubbleUpnpProfile.cs b/MediaBrowser.Dlna/Profiles/BubbleUpnpProfile.cs index a9af85346..8f3ad82ba 100644 --- a/MediaBrowser.Dlna/Profiles/BubbleUpnpProfile.cs +++ b/MediaBrowser.Dlna/Profiles/BubbleUpnpProfile.cs @@ -1,5 +1,5 @@ -using System.Xml.Serialization; -using MediaBrowser.Model.Dlna; +using MediaBrowser.Model.Dlna; +using System.Xml.Serialization; namespace MediaBrowser.Dlna.Profiles { @@ -10,8 +10,6 @@ namespace MediaBrowser.Dlna.Profiles { Name = "BubbleUPnp"; - TimelineOffsetSeconds = 5; - Identification = new DeviceIdentification { ModelName = "BubbleUPnp", @@ -27,16 +25,18 @@ namespace MediaBrowser.Dlna.Profiles new TranscodingProfile { Container = "mp3", - Type = DlnaProfileType.Audio, - AudioCodec = "mp3" + AudioCodec = "mp3", + Type = DlnaProfileType.Audio }, + new TranscodingProfile { Container = "ts", Type = DlnaProfileType.Video, - VideoCodec = "h264", - AudioCodec = "aac" + AudioCodec = "aac", + VideoCodec = "h264" }, + new TranscodingProfile { Container = "jpeg", @@ -48,21 +48,20 @@ namespace MediaBrowser.Dlna.Profiles { new DirectPlayProfile { - Container = "avi,mpeg,mkv,ts,mp4,mov,m4v,asf,webm,ogg,ogv,iso", + Container = "", Type = DlnaProfileType.Video }, new DirectPlayProfile { - Container = "mp3,flac,asf,off,oga,aac", + Container = "", Type = DlnaProfileType.Audio }, new DirectPlayProfile { + Container = "", Type = DlnaProfileType.Photo, - - Container = "jpeg,png,gif,bmp,tiff" } }; @@ -71,6 +70,77 @@ namespace MediaBrowser.Dlna.Profiles ContainerProfiles = new ContainerProfile[] { }; CodecProfiles = new CodecProfile[] { }; + + SubtitleProfiles = new[] + { + new SubtitleProfile + { + Format = "srt", + Method = SubtitleDeliveryMethod.External, + }, + + new SubtitleProfile + { + Format = "sub", + Method = SubtitleDeliveryMethod.External, + }, + + new SubtitleProfile + { + Format = "srt", + Method = SubtitleDeliveryMethod.Embed, + DidlMode = "", + }, + + new SubtitleProfile + { + Format = "ass", + Method = SubtitleDeliveryMethod.Embed, + DidlMode = "", + }, + + new SubtitleProfile + { + Format = "ssa", + Method = SubtitleDeliveryMethod.Embed, + DidlMode = "", + }, + + new SubtitleProfile + { + Format = "smi", + Method = SubtitleDeliveryMethod.Embed, + DidlMode = "", + }, + + new SubtitleProfile + { + Format = "dvdsub", + Method = SubtitleDeliveryMethod.Embed, + DidlMode = "", + }, + + new SubtitleProfile + { + Format = "pgs", + Method = SubtitleDeliveryMethod.Embed, + DidlMode = "", + }, + + new SubtitleProfile + { + Format = "pgssub", + Method = SubtitleDeliveryMethod.Embed, + DidlMode = "", + }, + + new SubtitleProfile + { + Format = "sub", + Method = SubtitleDeliveryMethod.Embed, + DidlMode = "", + } + }; } } } diff --git a/MediaBrowser.Dlna/Profiles/VlcProfile.cs b/MediaBrowser.Dlna/Profiles/VlcProfile.cs index 5b3f7c0d1..09d290f3a 100644 --- a/MediaBrowser.Dlna/Profiles/VlcProfile.cs +++ b/MediaBrowser.Dlna/Profiles/VlcProfile.cs @@ -1,5 +1,5 @@ -using System.Xml.Serialization; -using MediaBrowser.Model.Dlna; +using MediaBrowser.Model.Dlna; +using System.Xml.Serialization; namespace MediaBrowser.Dlna.Profiles { @@ -10,6 +10,7 @@ namespace MediaBrowser.Dlna.Profiles { Name = "Vlc"; + TimelineOffsetSeconds = 5; Identification = new DeviceIdentification @@ -27,16 +28,18 @@ namespace MediaBrowser.Dlna.Profiles new TranscodingProfile { Container = "mp3", - Type = DlnaProfileType.Audio, - AudioCodec = "mp3" + AudioCodec = "mp3", + Type = DlnaProfileType.Audio }, + new TranscodingProfile { Container = "ts", Type = DlnaProfileType.Video, - VideoCodec = "h264", - AudioCodec = "aac" + AudioCodec = "aac", + VideoCodec = "h264" }, + new TranscodingProfile { Container = "jpeg", @@ -48,21 +51,20 @@ namespace MediaBrowser.Dlna.Profiles { new DirectPlayProfile { - Container = "avi,mpeg,mkv,ts,mp4,mov,m4v,asf,webm,ogg,ogv,iso", + Container = "", Type = DlnaProfileType.Video }, new DirectPlayProfile { - Container = "mp3,flac,asf,off,oga,aac", + Container = "", Type = DlnaProfileType.Audio }, new DirectPlayProfile { + Container = "", Type = DlnaProfileType.Photo, - - Container = "jpeg,png,gif,bmp,tiff" } }; @@ -71,6 +73,77 @@ namespace MediaBrowser.Dlna.Profiles ContainerProfiles = new ContainerProfile[] { }; CodecProfiles = new CodecProfile[] { }; + + SubtitleProfiles = new[] + { + new SubtitleProfile + { + Format = "srt", + Method = SubtitleDeliveryMethod.External, + }, + + new SubtitleProfile + { + Format = "sub", + Method = SubtitleDeliveryMethod.External, + }, + + new SubtitleProfile + { + Format = "srt", + Method = SubtitleDeliveryMethod.Embed, + DidlMode = "", + }, + + new SubtitleProfile + { + Format = "ass", + Method = SubtitleDeliveryMethod.Embed, + DidlMode = "", + }, + + new SubtitleProfile + { + Format = "ssa", + Method = SubtitleDeliveryMethod.Embed, + DidlMode = "", + }, + + new SubtitleProfile + { + Format = "smi", + Method = SubtitleDeliveryMethod.Embed, + DidlMode = "", + }, + + new SubtitleProfile + { + Format = "dvdsub", + Method = SubtitleDeliveryMethod.Embed, + DidlMode = "", + }, + + new SubtitleProfile + { + Format = "pgs", + Method = SubtitleDeliveryMethod.Embed, + DidlMode = "", + }, + + new SubtitleProfile + { + Format = "pgssub", + Method = SubtitleDeliveryMethod.Embed, + DidlMode = "", + }, + + new SubtitleProfile + { + Format = "sub", + Method = SubtitleDeliveryMethod.Embed, + DidlMode = "", + } + }; } } } diff --git a/MediaBrowser.Dlna/Profiles/Xml/BubbleUPnp.xml b/MediaBrowser.Dlna/Profiles/Xml/BubbleUPnp.xml index 8261c7391..38b741454 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/BubbleUPnp.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/BubbleUPnp.xml @@ -28,16 +28,16 @@ 192000 DMS-1.50 http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_AC3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_HD_50_AC3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=44100;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=1:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/L16;rate=48000;channels=2:DLNA.ORG_PN=LPCM;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_BASE;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:audio/x-ms-wma:DLNA.ORG_PN=WMA_FULL;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_MED;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_LRG;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_TN;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG1;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_NTSC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_EU_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_EU_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_NA_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_NA_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=MPEG_TS_SD_KO_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_TS_SD_KO_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-msvideo:DLNA.ORG_PN=AVI;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-matroska:DLNA.ORG_PN=MATROSKA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_SD_AC3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_720p_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_MP_HD_1080i_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_HP_HD_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=AVC_MP4_LPCM;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_ASP_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_SP_L6_AAC;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mp4:DLNA.ORG_PN=MPEG4_P2_MP4_NDSD;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_SD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_AAC_MULT5_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=AVC_TS_MP_HD_MPEG1_L3_ISO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/vnd.dlna.mpeg-tts:DLNA.ORG_PN=AVC_TS_HD_50_LPCM_T;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_BASE;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_FULL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVMED_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-wmv:DLNA.ORG_PN=WMVHIGH_PRO;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L1_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L2_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000,http-get:*:video/x-ms-asf:DLNA.ORG_PN=VC1_ASF_AP_L3_WMA;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=01500000000000000000000000000000 - 5 + 0 false false false false - - - + + + @@ -47,5 +47,16 @@ - + + + + + + + + + + + + \ No newline at end of file diff --git a/MediaBrowser.Dlna/Profiles/Xml/Vlc.xml b/MediaBrowser.Dlna/Profiles/Xml/Vlc.xml index 02a35713d..a007a4aa3 100644 --- a/MediaBrowser.Dlna/Profiles/Xml/Vlc.xml +++ b/MediaBrowser.Dlna/Profiles/Xml/Vlc.xml @@ -35,9 +35,9 @@ false - - - + + + @@ -47,5 +47,16 @@ - + + + + + + + + + + + + \ No newline at end of file diff --git a/MediaBrowser.Providers/Music/ArtistMetadataService.cs b/MediaBrowser.Providers/Music/ArtistMetadataService.cs index 0c0339e12..21e9b006b 100644 --- a/MediaBrowser.Providers/Music/ArtistMetadataService.cs +++ b/MediaBrowser.Providers/Music/ArtistMetadataService.cs @@ -27,10 +27,12 @@ namespace MediaBrowser.Providers.Music { if (!item.IsLocked) { - var itemFilter = item.GetItemFilter(); - var taggedItems = item.IsAccessedByName ? - LibraryManager.RootFolder.GetRecursiveChildren(i => !i.IsFolder && itemFilter(i)).ToList() : + item.GetTaggedItems(new Controller.Entities.InternalItemsQuery() + { + Recursive = true, + IsFolder = false + }) : item.GetRecursiveChildren(i => i is IHasArtist && !i.IsFolder).ToList(); if (!item.LockedFields.Contains(MetadataFields.Genres)) diff --git a/MediaBrowser.Providers/TV/SeasonMetadataService.cs b/MediaBrowser.Providers/TV/SeasonMetadataService.cs index 1af116289..292923d82 100644 --- a/MediaBrowser.Providers/TV/SeasonMetadataService.cs +++ b/MediaBrowser.Providers/TV/SeasonMetadataService.cs @@ -7,6 +7,7 @@ using MediaBrowser.Model.Logging; using MediaBrowser.Providers.Manager; using System; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using CommonIO; @@ -31,6 +32,13 @@ namespace MediaBrowser.Providers.TV } } + if (isFullRefresh || currentUpdateType > ItemUpdateType.None) + { + var episodes = item.GetEpisodes().ToList(); + updateType |= SavePremiereDate(item, episodes); + updateType |= SaveIsMissing(item, episodes); + } + return updateType; } @@ -38,5 +46,38 @@ namespace MediaBrowser.Providers.TV { ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings); } + + private ItemUpdateType SavePremiereDate(Season item, List episodes) + { + var dates = episodes.Where(i => i.PremiereDate.HasValue).Select(i => i.PremiereDate.Value).ToList(); + + DateTime? premiereDate = null; + + if (dates.Count > 0) + { + premiereDate = dates.Min(); + } + + if (item.PremiereDate != premiereDate) + { + item.PremiereDate = premiereDate; + return ItemUpdateType.MetadataEdit; + } + + return ItemUpdateType.None; + } + + private ItemUpdateType SaveIsMissing(Season item, List episodes) + { + var isMissing = item.LocationType == LocationType.Virtual && episodes.All(i => i.IsMissingEpisode); + + if (item.IsMissingSeason != isMissing) + { + item.IsMissingSeason = isMissing; + return ItemUpdateType.MetadataEdit; + } + + return ItemUpdateType.None; + } } } diff --git a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs index fc07ebcac..509b22ee6 100644 --- a/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/TheTVDB/TvdbEpisodeProvider.cs @@ -749,7 +749,7 @@ namespace MediaBrowser.Providers.TV private void AddPeople(MetadataResult result, string val, string personType) { // Sometimes tvdb actors have leading spaces - foreach (var person in val.Split(new[] { '|', ',' }, StringSplitOptions.RemoveEmptyEntries) + foreach (var person in val.Split(new[] { '|' }, StringSplitOptions.RemoveEmptyEntries) .Where(i => !string.IsNullOrWhiteSpace(i)) .Select(str => new PersonInfo { Type = personType, Name = str.Trim() })) { diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 312eef9bf..dfbac47d5 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -115,11 +115,10 @@ namespace MediaBrowser.Server.Implementations.Dto { if (options.Fields.Contains(ItemFields.ItemCounts)) { - var itemFilter = byName.GetItemFilter(); - - var libraryItems = user != null ? - user.RootFolder.GetRecursiveChildren(user, itemFilter) : - _libraryManager.RootFolder.GetRecursiveChildren(itemFilter); + var libraryItems = byName.GetTaggedItems(new InternalItemsQuery(user) + { + Recursive = true + }); SetItemByNameInfo(item, dto, libraryItems.ToList(), user); } @@ -618,9 +617,12 @@ namespace MediaBrowser.Server.Implementations.Dto { if (!string.IsNullOrEmpty(item.Album)) { - var parentAlbum = _libraryManager.RootFolder - .GetRecursiveChildren(i => i is MusicAlbum && string.Equals(i.Name, item.Album, StringComparison.OrdinalIgnoreCase)) - .FirstOrDefault(); + var parentAlbum = _libraryManager.GetItemList(new InternalItemsQuery + { + IncludeItemTypes = new[] { typeof(MusicAlbum).Name }, + Name = item.Album + + }).FirstOrDefault(); if (parentAlbum != null) { diff --git a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs index f637160be..0e211937f 100644 --- a/MediaBrowser.Server.Implementations/Library/UserDataManager.cs +++ b/MediaBrowser.Server.Implementations/Library/UserDataManager.cs @@ -140,6 +140,54 @@ namespace MediaBrowser.Server.Implementations.Library return Repository.GetAllUserData(userId); } + public UserItemData GetUserData(Guid userId, List keys) + { + if (userId == Guid.Empty) + { + throw new ArgumentNullException("userId"); + } + if (keys == null) + { + throw new ArgumentNullException("keys"); + } + + lock (_userData) + { + foreach (var key in keys) + { + var cacheKey = GetCacheKey(userId, key); + UserItemData value; + if (_userData.TryGetValue(cacheKey, out value)) + { + return value; + } + + value = Repository.GetUserData(userId, key); + + if (value != null) + { + _userData[cacheKey] = value; + return value; + } + } + + if (keys.Count > 0) + { + var key = keys[0]; + var cacheKey = GetCacheKey(userId, key); + var userdata = new UserItemData + { + UserId = userId, + Key = key + }; + _userData[cacheKey] = userdata; + return userdata; + } + + return null; + } + } + /// /// Gets the user data. /// @@ -166,27 +214,22 @@ namespace MediaBrowser.Server.Implementations.Library return value; } - value = GetUserDataFromRepository(userId, key); + value = Repository.GetUserData(userId, key); + + if (value == null) + { + value = new UserItemData + { + UserId = userId, + Key = key + }; + } + _userData[cacheKey] = value; return value; } } - private UserItemData GetUserDataFromRepository(Guid userId, string key) - { - var data = Repository.GetUserData(userId, key); - - if (data == null) - { - data = new UserItemData - { - UserId = userId, - Key = key - }; - } - return data; - } - /// /// Gets the internal key. /// @@ -200,22 +243,22 @@ namespace MediaBrowser.Server.Implementations.Library public UserItemData GetUserData(IHasUserData user, IHasUserData item) { - return GetUserData(user.Id, item.GetUserDataKeys().First()); + return GetUserData(user.Id, item); } public UserItemData GetUserData(string userId, IHasUserData item) { - return GetUserData(userId, item.GetUserDataKeys().First()); + return GetUserData(new Guid(userId), item); } public UserItemData GetUserData(Guid userId, IHasUserData item) { - return GetUserData(userId, item.GetUserDataKeys().First()); + return GetUserData(userId, item.GetUserDataKeys()); } public UserItemDataDto GetUserDataDto(IHasUserData item, User user) { - var userData = GetUserData(user.Id, item.GetUserDataKeys().First()); + var userData = GetUserData(user.Id, item); var dto = GetUserItemDataDto(userData); item.FillUserDataDtoValues(dto, userData, user); @@ -302,10 +345,5 @@ namespace MediaBrowser.Server.Implementations.Library return playedToCompletion; } - - public UserItemData GetUserData(string userId, string key) - { - return GetUserData(new Guid(userId), key); - } } } diff --git a/MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs b/MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs index 00dc8e6a1..c1803b5e4 100644 --- a/MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs +++ b/MediaBrowser.Server.Implementations/Library/Validators/StudiosValidator.cs @@ -2,6 +2,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Model.Logging; using System; +using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -34,20 +35,25 @@ namespace MediaBrowser.Server.Implementations.Library.Validators /// Task. public async Task Run(IProgress progress, CancellationToken cancellationToken) { - var items = _libraryManager.GetItemList(new InternalItemsQuery - { - IncludeItemTypes = new[] { typeof(Studio).Name } - - }).ToList(); + var items = _libraryManager.RootFolder.GetRecursiveChildren(i => true) + .SelectMany(i => i.Studios) + .DistinctNames() + .ToList(); var numComplete = 0; var count = items.Count; - foreach (var item in items) + var validIds = new List(); + + foreach (var name in items) { try { - await item.RefreshMetadata(cancellationToken).ConfigureAwait(false); + var itemByName = _libraryManager.GetStudio(name); + + validIds.Add(itemByName.Id); + + await itemByName.RefreshMetadata(cancellationToken).ConfigureAwait(false); } catch (OperationCanceledException) { @@ -56,7 +62,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators } catch (Exception ex) { - _logger.ErrorException("Error refreshing {0}", ex, item.Name); + _logger.ErrorException("Error refreshing {0}", ex, name); } numComplete++; diff --git a/MediaBrowser.Server.Implementations/Library/Validators/YearsPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/Validators/YearsPostScanTask.cs index a6dbb99da..7f52a4506 100644 --- a/MediaBrowser.Server.Implementations/Library/Validators/YearsPostScanTask.cs +++ b/MediaBrowser.Server.Implementations/Library/Validators/YearsPostScanTask.cs @@ -25,7 +25,7 @@ namespace MediaBrowser.Server.Implementations.Library.Validators var count = maxYear - yearNumber + 1; var numComplete = 0; - while (yearNumber < DateTime.UtcNow.Year + 3) + while (yearNumber < maxYear) { try { diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index 7e7dfe6eb..812d57ddd 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -1870,9 +1870,9 @@ namespace MediaBrowser.Server.Implementations.Persistence using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult)) { - Logger.Debug("GetItemIdsList query time: {0}ms. Query: {1}", - Convert.ToInt32((DateTime.UtcNow - now).TotalMilliseconds), - cmd.CommandText); + //Logger.Debug("GetItemIdsList query time: {0}ms. Query: {1}", + // Convert.ToInt32((DateTime.UtcNow - now).TotalMilliseconds), + // cmd.CommandText); while (reader.Read()) {