From 9d784823580b3f9a14a3e4669903babdb2ee57f4 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Fri, 1 Sep 2017 15:24:39 -0400 Subject: fix skiasharp reference --- MediaBrowser.Controller/Entities/BaseItem.cs | 61 ++++++++++++++++------------ 1 file changed, 34 insertions(+), 27 deletions(-) (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs') diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 513b85d8b1..c41d3e0cda 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -186,21 +186,6 @@ namespace MediaBrowser.Controller.Entities } } - [IgnoreDataMember] - public string SlugName - { - get - { - var name = Name; - if (string.IsNullOrWhiteSpace(name)) - { - return string.Empty; - } - - return SlugReplaceChars.Aggregate(name, (current, c) => current.Replace(c, SlugChar)); - } - } - [IgnoreDataMember] public bool IsUnaired { @@ -664,27 +649,34 @@ namespace MediaBrowser.Controller.Entities } var sortable = Name.Trim().ToLower(); - sortable = ConfigurationManager.Configuration.SortRemoveCharacters.Aggregate(sortable, (current, search) => current.Replace(search.ToLower(), string.Empty)); - sortable = ConfigurationManager.Configuration.SortReplaceCharacters.Aggregate(sortable, (current, search) => current.Replace(search.ToLower(), " ")); + foreach (var removeChar in ConfigurationManager.Configuration.SortRemoveCharacters) + { + sortable = sortable.Replace(removeChar, string.Empty); + } + + foreach (var replaceChar in ConfigurationManager.Configuration.SortReplaceCharacters) + { + sortable = sortable.Replace(replaceChar, " "); + } foreach (var search in ConfigurationManager.Configuration.SortRemoveWords) { - var searchLower = search.ToLower(); // Remove from beginning if a space follows - if (sortable.StartsWith(searchLower + " ")) + if (sortable.StartsWith(search + " ")) { - sortable = sortable.Remove(0, searchLower.Length + 1); + sortable = sortable.Remove(0, search.Length + 1); } // Remove from middle if surrounded by spaces - sortable = sortable.Replace(" " + searchLower + " ", " "); + sortable = sortable.Replace(" " + search + " ", " "); // Remove from end if followed by a space - if (sortable.EndsWith(" " + searchLower)) + if (sortable.EndsWith(" " + search)) { - sortable = sortable.Remove(sortable.Length - (searchLower.Length + 1)); + sortable = sortable.Remove(sortable.Length - (search.Length + 1)); } } + return ModifySortChunks(sortable); } @@ -771,7 +763,15 @@ namespace MediaBrowser.Controller.Entities public T FindParent() where T : Folder { - return GetParents().OfType().FirstOrDefault(); + foreach (var parent in GetParents()) + { + var item = parent as T; + if (item != null) + { + return item; + } + } + return null; } [IgnoreDataMember] @@ -2140,8 +2140,8 @@ namespace MediaBrowser.Controller.Entities } var filename = System.IO.Path.GetFileNameWithoutExtension(Path); - var extensions = new[] { ".nfo", ".xml", ".srt" }.ToList(); - extensions.AddRange(SupportedImageExtensionsList); + var extensions = new List { ".nfo", ".xml", ".srt" }; + extensions.AddRange(SupportedImageExtensions); return FileSystem.GetFiles(FileSystem.GetDirectoryName(Path), extensions.ToArray(extensions.Count), false, false) .Where(i => System.IO.Path.GetFileNameWithoutExtension(i.FullName).StartsWith(filename, StringComparison.OrdinalIgnoreCase)) @@ -2392,7 +2392,14 @@ namespace MediaBrowser.Controller.Entities return this; } - return GetParents().FirstOrDefault(i => i.IsTopParent); + foreach (var parent in GetParents()) + { + if (parent.IsTopParent) + { + return parent; + } + } + return null; } [IgnoreDataMember] -- cgit v1.2.3 From 38fe239f4490eb4bf839e9b872f7d9c8172decf9 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Wed, 13 Sep 2017 14:41:48 -0400 Subject: 3.2.30.19 --- .../Channels/ChannelManager.cs | 4 ++ .../LiveTv/LiveTvManager.cs | 5 +++ .../LiveTv/LiveTvMediaSourceProvider.cs | 2 + MediaBrowser.Api/ItemUpdateService.cs | 2 + MediaBrowser.Api/StartupWizardService.cs | 1 - MediaBrowser.Controller/Entities/Audio/Audio.cs | 48 +++++++--------------- .../Entities/Audio/MusicAlbum.cs | 9 ++-- MediaBrowser.Controller/Entities/BaseItem.cs | 26 ++++++++++-- MediaBrowser.Controller/Entities/IHasMetadata.cs | 2 + .../Configuration/ServerConfiguration.cs | 1 - .../BoxSets/BoxSetMetadataService.cs | 4 +- MediaBrowser.Providers/Manager/MetadataService.cs | 18 ++++---- .../Music/AlbumMetadataService.cs | 4 +- .../Music/ArtistMetadataService.cs | 4 +- .../Playlists/PlaylistMetadataService.cs | 4 +- .../TV/EpisodeMetadataService.cs | 4 +- MediaBrowser.Providers/TV/SeasonMetadataService.cs | 4 +- SharedVersion.cs | 2 +- 18 files changed, 78 insertions(+), 66 deletions(-) (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs') diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 2f726f8abc..d3950929d4 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -426,6 +426,8 @@ namespace Emby.Server.Implementations.Channels item.Name = channelInfo.Name; } + item.OnMetadataChanged(); + if (isNew) { _libraryManager.CreateItem(item, cancellationToken); @@ -1384,6 +1386,8 @@ namespace Emby.Server.Implementations.Channels item.SetImagePath(ImageType.Primary, info.ImageUrl); } + item.OnMetadataChanged(); + if (isNew) { _libraryManager.CreateItem(item, cancellationToken); diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index dc212492e0..870a3b4937 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -752,6 +752,11 @@ namespace Emby.Server.Implementations.LiveTv } } + if (isNew || isUpdated) + { + item.OnMetadataChanged(); + } + return new Tuple(item, isNew, isUpdated); } diff --git a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs index 0e52f874d4..62906f5d4e 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs @@ -142,6 +142,8 @@ namespace Emby.Server.Implementations.LiveTv var info = await _liveTvManager.GetChannelStream(keys[1], mediaSourceId, cancellationToken).ConfigureAwait(false); stream = info.Item1; directStreamProvider = info.Item2; + + allowLiveStreamProbe = false; } else { diff --git a/MediaBrowser.Api/ItemUpdateService.cs b/MediaBrowser.Api/ItemUpdateService.cs index 9e83cf680f..53a67ff712 100644 --- a/MediaBrowser.Api/ItemUpdateService.cs +++ b/MediaBrowser.Api/ItemUpdateService.cs @@ -214,6 +214,8 @@ namespace MediaBrowser.Api UpdateItem(request, item); + item.OnMetadataChanged(); + await item.UpdateToRepository(ItemUpdateType.MetadataEdit, CancellationToken.None).ConfigureAwait(false); if (isLockedChanged && item.IsFolder) diff --git a/MediaBrowser.Api/StartupWizardService.cs b/MediaBrowser.Api/StartupWizardService.cs index b15e06c9c0..22f1f3b62c 100644 --- a/MediaBrowser.Api/StartupWizardService.cs +++ b/MediaBrowser.Api/StartupWizardService.cs @@ -89,7 +89,6 @@ namespace MediaBrowser.Api private void SetWizardFinishValues(ServerConfiguration config) { - config.EnableStandaloneMusicKeys = true; config.EnableCaseSensitiveItemIds = true; config.SkipDeserializationForBasicTypes = true; config.EnableLocalizedGuids = true; diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index 3ebf4da009..02a9f15a95 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -154,46 +154,28 @@ namespace MediaBrowser.Controller.Entities.Audio { var list = base.GetUserDataKeys(); - if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys) - { - var songKey = IndexNumber.HasValue ? IndexNumber.Value.ToString("0000") : string.Empty; - - - if (ParentIndexNumber.HasValue) - { - songKey = ParentIndexNumber.Value.ToString("0000") + "-" + songKey; - } - songKey += Name; + var songKey = IndexNumber.HasValue ? IndexNumber.Value.ToString("0000") : string.Empty; - if (!string.IsNullOrWhiteSpace(Album)) - { - songKey = Album + "-" + songKey; - } - - var albumArtist = AlbumArtists.Length == 0 ? null : AlbumArtists[0]; - if (!string.IsNullOrWhiteSpace(albumArtist)) - { - songKey = albumArtist + "-" + songKey; - } - list.Insert(0, songKey); - } - else + if (ParentIndexNumber.HasValue) { - var parent = AlbumEntity; + songKey = ParentIndexNumber.Value.ToString("0000") + "-" + songKey; + } + songKey += Name; - if (parent != null && IndexNumber.HasValue) - { - list.InsertRange(0, parent.GetUserDataKeys().Select(i => - { - var songKey = (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("0000 - ") : "") - + IndexNumber.Value.ToString("0000 - "); + if (!string.IsNullOrWhiteSpace(Album)) + { + songKey = Album + "-" + songKey; + } - return i + songKey; - })); - } + var albumArtist = AlbumArtists.Length == 0 ? null : AlbumArtists[0]; + if (!string.IsNullOrWhiteSpace(albumArtist)) + { + songKey = albumArtist + "-" + songKey; } + list.Insert(0, songKey); + return list; } diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs index 7af8161cab..acda9ae02b 100644 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs @@ -145,13 +145,10 @@ namespace MediaBrowser.Controller.Entities.Audio { var list = base.GetUserDataKeys(); - if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys) + var albumArtist = AlbumArtist; + if (!string.IsNullOrWhiteSpace(albumArtist)) { - var albumArtist = AlbumArtist; - if (!string.IsNullOrWhiteSpace(albumArtist)) - { - list.Insert(0, albumArtist + "-" + Name); - } + list.Insert(0, albumArtist + "-" + Name); } var id = this.GetProviderId(MetadataProviders.MusicBrainzAlbum); diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index c41d3e0cda..4416c5e916 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -918,9 +918,10 @@ namespace MediaBrowser.Controller.Entities { get { - if (!string.IsNullOrWhiteSpace(OfficialRating)) + var officialRating = OfficialRating; + if (!string.IsNullOrWhiteSpace(officialRating)) { - return OfficialRating; + return officialRating; } var parent = DisplayParent; @@ -938,9 +939,10 @@ namespace MediaBrowser.Controller.Entities { get { - if (!string.IsNullOrWhiteSpace(CustomRating)) + var customRating = CustomRating; + if (!string.IsNullOrWhiteSpace(customRating)) { - return CustomRating; + return customRating; } var parent = DisplayParent; @@ -2480,5 +2482,21 @@ namespace MediaBrowser.Controller.Entities { return null; } + + public virtual ItemUpdateType OnMetadataChanged() + { + var updateType = ItemUpdateType.None; + + var item = this; + + var inheritedParentalRatingValue = item.GetInheritedParentalRatingValue() ?? 0; + if (inheritedParentalRatingValue != item.InheritedParentalRatingValue) + { + item.InheritedParentalRatingValue = inheritedParentalRatingValue; + updateType |= ItemUpdateType.MetadataImport; + } + + return updateType; + } } } \ No newline at end of file diff --git a/MediaBrowser.Controller/Entities/IHasMetadata.cs b/MediaBrowser.Controller/Entities/IHasMetadata.cs index 59d9bd9f90..4146686b21 100644 --- a/MediaBrowser.Controller/Entities/IHasMetadata.cs +++ b/MediaBrowser.Controller/Entities/IHasMetadata.cs @@ -266,6 +266,8 @@ namespace MediaBrowser.Controller.Entities int? ProductionYear { get; set; } string[] Tags { get; set; } + + ItemUpdateType OnMetadataChanged(); } public static class HasMetadataExtensions diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 5177a757a9..ae04bbaab6 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -179,7 +179,6 @@ namespace MediaBrowser.Model.Configuration public int SchemaVersion { get; set; } public bool EnableAnonymousUsageReporting { get; set; } - public bool EnableStandaloneMusicKeys { get; set; } public bool EnableFolderView { get; set; } public bool EnableGroupingIntoCollections { get; set; } public bool DisplaySpecialsWithinSeasons { get; set; } diff --git a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs index 12748a8a77..2c3dc0e31d 100644 --- a/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs +++ b/MediaBrowser.Providers/BoxSets/BoxSetMetadataService.cs @@ -14,9 +14,9 @@ namespace MediaBrowser.Providers.BoxSets { public class BoxSetMetadataService : MetadataService { - protected override ItemUpdateType BeforeSave(BoxSet item, bool isFullRefresh, ItemUpdateType currentUpdateType) + protected override ItemUpdateType BeforeSaveInternal(BoxSet item, bool isFullRefresh, ItemUpdateType currentUpdateType) { - var updateType = base.BeforeSave(item, isFullRefresh, currentUpdateType); + var updateType = base.BeforeSaveInternal(item, isFullRefresh, currentUpdateType); if (isFullRefresh || currentUpdateType > ItemUpdateType.None) { diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index 9a7ced0a5c..ae029cc594 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -281,7 +281,16 @@ namespace MediaBrowser.Providers.Manager /// if set to true [is full refresh]. /// Type of the current update. /// ItemUpdateType. - protected virtual ItemUpdateType BeforeSave(TItemType item, bool isFullRefresh, ItemUpdateType currentUpdateType) + private ItemUpdateType BeforeSave(TItemType item, bool isFullRefresh, ItemUpdateType currentUpdateType) + { + var updateType = BeforeSaveInternal(item, isFullRefresh, currentUpdateType); + + updateType |= item.OnMetadataChanged(); + + return updateType; + } + + protected virtual ItemUpdateType BeforeSaveInternal(TItemType item, bool isFullRefresh, ItemUpdateType currentUpdateType) { var updateType = ItemUpdateType.None; @@ -295,13 +304,6 @@ namespace MediaBrowser.Providers.Manager updateType |= ItemUpdateType.MetadataImport; } - var inheritedParentalRatingValue = item.GetInheritedParentalRatingValue() ?? 0; - if (inheritedParentalRatingValue != item.InheritedParentalRatingValue) - { - item.InheritedParentalRatingValue = inheritedParentalRatingValue; - updateType |= ItemUpdateType.MetadataImport; - } - return updateType; } diff --git a/MediaBrowser.Providers/Music/AlbumMetadataService.cs b/MediaBrowser.Providers/Music/AlbumMetadataService.cs index 4230c517ae..48f520681a 100644 --- a/MediaBrowser.Providers/Music/AlbumMetadataService.cs +++ b/MediaBrowser.Providers/Music/AlbumMetadataService.cs @@ -16,9 +16,9 @@ namespace MediaBrowser.Providers.Music { public class AlbumMetadataService : MetadataService { - protected override ItemUpdateType BeforeSave(MusicAlbum item, bool isFullRefresh, ItemUpdateType currentUpdateType) + protected override ItemUpdateType BeforeSaveInternal(MusicAlbum item, bool isFullRefresh, ItemUpdateType currentUpdateType) { - var updateType = base.BeforeSave(item, isFullRefresh, currentUpdateType); + var updateType = base.BeforeSaveInternal(item, isFullRefresh, currentUpdateType); if (isFullRefresh || currentUpdateType > ItemUpdateType.None) { diff --git a/MediaBrowser.Providers/Music/ArtistMetadataService.cs b/MediaBrowser.Providers/Music/ArtistMetadataService.cs index 0ff161576f..70ae525445 100644 --- a/MediaBrowser.Providers/Music/ArtistMetadataService.cs +++ b/MediaBrowser.Providers/Music/ArtistMetadataService.cs @@ -15,9 +15,9 @@ namespace MediaBrowser.Providers.Music { public class ArtistMetadataService : MetadataService { - protected override ItemUpdateType BeforeSave(MusicArtist item, bool isFullRefresh, ItemUpdateType currentUpdateType) + protected override ItemUpdateType BeforeSaveInternal(MusicArtist item, bool isFullRefresh, ItemUpdateType currentUpdateType) { - var updateType = base.BeforeSave(item, isFullRefresh, currentUpdateType); + var updateType = base.BeforeSaveInternal(item, isFullRefresh, currentUpdateType); if (isFullRefresh || currentUpdateType > ItemUpdateType.None) { diff --git a/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs b/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs index d39d3baf5d..a81facfb51 100644 --- a/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs +++ b/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs @@ -34,9 +34,9 @@ namespace MediaBrowser.Providers.Playlists } } - protected override ItemUpdateType BeforeSave(Playlist item, bool isFullRefresh, ItemUpdateType currentUpdateType) + protected override ItemUpdateType BeforeSaveInternal(Playlist item, bool isFullRefresh, ItemUpdateType currentUpdateType) { - var updateType = base.BeforeSave(item, isFullRefresh, currentUpdateType); + var updateType = base.BeforeSaveInternal(item, isFullRefresh, currentUpdateType); if (isFullRefresh || currentUpdateType > ItemUpdateType.None) { diff --git a/MediaBrowser.Providers/TV/EpisodeMetadataService.cs b/MediaBrowser.Providers/TV/EpisodeMetadataService.cs index 29533a46be..49175f62f9 100644 --- a/MediaBrowser.Providers/TV/EpisodeMetadataService.cs +++ b/MediaBrowser.Providers/TV/EpisodeMetadataService.cs @@ -16,9 +16,9 @@ namespace MediaBrowser.Providers.TV { public class EpisodeMetadataService : MetadataService { - protected override ItemUpdateType BeforeSave(Episode item, bool isFullRefresh, ItemUpdateType currentUpdateType) + protected override ItemUpdateType BeforeSaveInternal(Episode item, bool isFullRefresh, ItemUpdateType currentUpdateType) { - var updateType = base.BeforeSave(item, isFullRefresh, currentUpdateType); + var updateType = base.BeforeSaveInternal(item, isFullRefresh, currentUpdateType); var seriesName = item.FindSeriesName(); if (!string.Equals(item.SeriesName, seriesName, StringComparison.Ordinal)) diff --git a/MediaBrowser.Providers/TV/SeasonMetadataService.cs b/MediaBrowser.Providers/TV/SeasonMetadataService.cs index 7cd4087911..4e712d3e36 100644 --- a/MediaBrowser.Providers/TV/SeasonMetadataService.cs +++ b/MediaBrowser.Providers/TV/SeasonMetadataService.cs @@ -17,9 +17,9 @@ namespace MediaBrowser.Providers.TV { public class SeasonMetadataService : MetadataService { - protected override ItemUpdateType BeforeSave(Season item, bool isFullRefresh, ItemUpdateType currentUpdateType) + protected override ItemUpdateType BeforeSaveInternal(Season item, bool isFullRefresh, ItemUpdateType currentUpdateType) { - var updateType = base.BeforeSave(item, isFullRefresh, currentUpdateType); + var updateType = base.BeforeSaveInternal(item, isFullRefresh, currentUpdateType); if (item.IndexNumber.HasValue && item.IndexNumber.Value == 0) { diff --git a/SharedVersion.cs b/SharedVersion.cs index 1f5bfba76d..8d5353ca56 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,3 +1,3 @@ using System.Reflection; -[assembly: AssemblyVersion("3.2.30.18")] +[assembly: AssemblyVersion("3.2.30.19")] -- cgit v1.2.3 From cdd79ec7e2fcea806be7a9b50764b1ad473d5970 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 18 Sep 2017 12:52:22 -0400 Subject: update owned items --- .../Collections/CollectionImageProvider.cs | 2 +- .../Data/SqliteItemRepository.cs | 50 +++++++--- Emby.Server.Implementations/Dto/DtoService.cs | 2 +- .../EntryPoints/LibraryChangedNotifier.cs | 10 +- .../EntryPoints/RefreshUsersMetadata.cs | 59 ++++++++--- .../EntryPoints/UserDataChangeNotifier.cs | 2 +- Emby.Server.Implementations/IO/FileRefresher.cs | 2 +- .../Library/LibraryManager.cs | 36 ++++--- Emby.Server.Implementations/Library/UserManager.cs | 9 +- .../LiveTv/EmbyTV/DirectRecorder.cs | 4 + .../LiveTv/EmbyTV/EmbyTV.cs | 54 +++++------ .../LiveTv/LiveTvManager.cs | 6 +- .../TunerHosts/HdHomerun/HdHomerunHttpStream.cs | 2 +- .../Playlists/PlaylistImageProvider.cs | 2 +- .../Entities/AggregateFolder.cs | 2 +- MediaBrowser.Controller/Entities/BaseItem.cs | 108 ++++++++++++++++----- .../Entities/CollectionFolder.cs | 2 +- MediaBrowser.Controller/Entities/Folder.cs | 103 +++++++++++++------- MediaBrowser.Controller/Entities/IHasTrailers.cs | 2 +- MediaBrowser.Controller/Entities/ItemImageInfo.cs | 6 -- MediaBrowser.Controller/Entities/Movies/Movie.cs | 15 ++- MediaBrowser.Controller/Entities/TV/Series.cs | 10 +- MediaBrowser.Controller/Entities/User.cs | 3 + .../Providers/MetadataRefreshOptions.cs | 28 +++++- MediaBrowser.Model/LiveTv/LiveTvOptions.cs | 1 - .../Manager/GenericPriorityQueue.cs | 15 +-- .../Manager/ItemImageProvider.cs | 5 +- MediaBrowser.Providers/Manager/MetadataService.cs | 3 +- .../MediaInfo/FFProbeProvider.cs | 5 + .../MediaInfo/VideoImageProvider.cs | 2 +- 30 files changed, 373 insertions(+), 177 deletions(-) (limited to 'MediaBrowser.Controller/Entities/BaseItem.cs') diff --git a/Emby.Server.Implementations/Collections/CollectionImageProvider.cs b/Emby.Server.Implementations/Collections/CollectionImageProvider.cs index c7378956dd..f47e2d10a7 100644 --- a/Emby.Server.Implementations/Collections/CollectionImageProvider.cs +++ b/Emby.Server.Implementations/Collections/CollectionImageProvider.cs @@ -57,7 +57,7 @@ namespace Emby.Server.Implementations.Collections return subItem; } - var parent = subItem.GetParent(); + var parent = subItem.IsOwnedItem ? subItem.GetOwner() : subItem.GetParent(); if (parent != null && parent.HasImage(ImageType.Primary)) { diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 6811e42ec0..2186982d3e 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -253,6 +253,7 @@ namespace Emby.Server.Implementations.Data AddColumn(db, "TypedBaseItems", "ExternalId", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "SeriesPresentationUniqueKey", "Text", existingColumnNames); AddColumn(db, "TypedBaseItems", "ShowId", "Text", existingColumnNames); + AddColumn(db, "TypedBaseItems", "OwnerId", "Text", existingColumnNames); existingColumnNames = GetColumnNames(db, "ItemValues"); AddColumn(db, "ItemValues", "CleanValue", "Text", existingColumnNames); @@ -459,7 +460,8 @@ namespace Emby.Server.Implementations.Data "AlbumArtists", "ExternalId", "SeriesPresentationUniqueKey", - "ShowId" + "ShowId", + "OwnerId" }; private readonly string[] _mediaStreamSaveColumns = @@ -580,7 +582,8 @@ namespace Emby.Server.Implementations.Data "AlbumArtists", "ExternalId", "SeriesPresentationUniqueKey", - "ShowId" + "ShowId", + "OwnerId" }; var saveItemCommandCommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; @@ -784,13 +787,14 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBind("@PremiereDate", item.PremiereDate); saveItemStatement.TryBind("@ProductionYear", item.ProductionYear); - if (item.ParentId == Guid.Empty) + var parentId = item.ParentId; + if (parentId == Guid.Empty) { saveItemStatement.TryBindNull("@ParentId"); } else { - saveItemStatement.TryBind("@ParentId", item.ParentId); + saveItemStatement.TryBind("@ParentId", parentId); } if (item.Genres.Count > 0) @@ -1057,6 +1061,16 @@ namespace Emby.Server.Implementations.Data saveItemStatement.TryBindNull("@ShowId"); } + var ownerId = item.OwnerId; + if (ownerId != Guid.Empty) + { + saveItemStatement.TryBind("@OwnerId", ownerId); + } + else + { + saveItemStatement.TryBindNull("@OwnerId"); + } + saveItemStatement.MoveNext(); } @@ -1156,16 +1170,14 @@ namespace Emby.Server.Implementations.Data delimeter + image.DateModified.Ticks.ToString(CultureInfo.InvariantCulture) + delimeter + - image.Type + - delimeter + - image.IsPlaceholder; + image.Type; } public ItemImageInfo ItemImageInfoFromValueString(string value) { var parts = value.Split(new[] { '*' }, StringSplitOptions.None); - if (parts.Length != 4) + if (parts.Length < 3) { return null; } @@ -1173,9 +1185,18 @@ namespace Emby.Server.Implementations.Data var image = new ItemImageInfo(); image.Path = parts[0]; - image.DateModified = new DateTime(long.Parse(parts[1], CultureInfo.InvariantCulture), DateTimeKind.Utc); - image.Type = (ImageType)Enum.Parse(typeof(ImageType), parts[2], true); - image.IsPlaceholder = string.Equals(parts[3], true.ToString(), StringComparison.OrdinalIgnoreCase); + + long ticks; + if (long.TryParse(parts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out ticks)) + { + image.DateModified = new DateTime(ticks, DateTimeKind.Utc); + } + + ImageType type; + if (Enum.TryParse(parts[2], true, out type)) + { + image.Type = type; + } return image; } @@ -1965,6 +1986,12 @@ namespace Emby.Server.Implementations.Data } } + if (!reader.IsDBNull(index)) + { + item.OwnerId = reader.GetGuid(index); + } + index++; + return item; } @@ -4467,7 +4494,6 @@ namespace Emby.Server.Implementations.Data } } - var includedItemByNameTypes = GetItemByNameTypesInQuery(query).SelectMany(MapIncludeItemTypes).ToList(); var enableItemsByName = (query.IncludeItemsByName ?? false) && includedItemByNameTypes.Count > 0; diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index b57662e311..1854829a24 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -1487,7 +1487,7 @@ namespace Emby.Server.Implementations.Dto } } - var parent = currentItem.DisplayParent ?? currentItem.GetParent(); + var parent = currentItem.DisplayParent ?? (currentItem.IsOwnedItem ? currentItem.GetOwner() : currentItem.GetParent()); if (parent == null && !(originalItem is UserRootFolder) && !(originalItem is UserView) && !(originalItem is AggregateFolder) && !(originalItem is ICollectionFolder) && !(originalItem is Channel)) { diff --git a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs index 796d8cf482..299da07445 100644 --- a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs @@ -198,9 +198,10 @@ namespace Emby.Server.Implementations.EntryPoints LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite); } - if (e.Item.Parent != null) + var parent = e.Item.GetParent() as Folder; + if (parent != null) { - _foldersAddedTo.Add(e.Item.Parent); + _foldersAddedTo.Add(parent); } _itemsAdded.Add(e.Item); @@ -259,9 +260,10 @@ namespace Emby.Server.Implementations.EntryPoints LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite); } - if (e.Item.Parent != null) + var parent = e.Item.GetParent() as Folder; + if (parent != null) { - _foldersRemovedFrom.Add(e.Item.Parent); + _foldersRemovedFrom.Add(parent); } _itemsRemoved.Add(e.Item); diff --git a/Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs b/Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs index 13e14be36f..4c16b1d39e 100644 --- a/Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs +++ b/Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs @@ -1,43 +1,74 @@ using System; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Plugins; using System.Threading; +using MediaBrowser.Model.Tasks; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.IO; namespace Emby.Server.Implementations.EntryPoints { /// /// Class RefreshUsersMetadata /// - public class RefreshUsersMetadata : IServerEntryPoint + public class RefreshUsersMetadata : IScheduledTask, IConfigurableScheduledTask { /// /// The _user manager /// private readonly IUserManager _userManager; + private IFileSystem _fileSystem; + + public string Name => "Refresh Users"; + + public string Key => "RefreshUsers"; + + public string Description => "Refresh user infos"; + + public string Category + { + get { return "Library"; } + } + + public bool IsHidden => true; + + public bool IsEnabled => true; + + public bool IsLogged => true; /// /// Initializes a new instance of the class. /// - /// The user manager. - public RefreshUsersMetadata(IUserManager userManager) + public RefreshUsersMetadata(IUserManager userManager, IFileSystem fileSystem) { _userManager = userManager; + _fileSystem = fileSystem; } - /// - /// Runs this instance. - /// - public async void Run() + public async Task Execute(CancellationToken cancellationToken, IProgress progress) { - await _userManager.RefreshUsersMetadata(CancellationToken.None).ConfigureAwait(false); + var users = _userManager.Users.ToList(); + + foreach (var user in users) + { + cancellationToken.ThrowIfCancellationRequested(); + + await user.RefreshMetadata(new MetadataRefreshOptions(_fileSystem), cancellationToken).ConfigureAwait(false); + } } - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() + public IEnumerable GetDefaultTriggers() { - GC.SuppressFinalize(this); + return new List + { + new TaskTriggerInfo + { + IntervalTicks = TimeSpan.FromDays(1).Ticks, + Type = TaskTriggerInfo.TriggerInterval + } + }; } } } diff --git a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs index 4a7182a43c..13c72bf3c7 100644 --- a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs @@ -77,7 +77,7 @@ namespace Emby.Server.Implementations.EntryPoints // Go up one level for indicators if (baseItem != null) { - var parent = baseItem.GetParent(); + var parent = baseItem.IsOwnedItem ? baseItem.GetOwner() : baseItem.GetParent(); if (parent != null) { diff --git a/Emby.Server.Implementations/IO/FileRefresher.cs b/Emby.Server.Implementations/IO/FileRefresher.cs index 20de8a5180..315bee103e 100644 --- a/Emby.Server.Implementations/IO/FileRefresher.cs +++ b/Emby.Server.Implementations/IO/FileRefresher.cs @@ -209,7 +209,7 @@ namespace Emby.Server.Implementations.IO // If the item has been deleted find the first valid parent that still exists while (!_fileSystem.DirectoryExists(item.Path) && !_fileSystem.FileExists(item.Path)) { - item = item.GetParent(); + item = item.IsOwnedItem ? item.GetOwner() : item.GetParent(); if (item == null) { diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 139435faa7..eab52e5e81 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -386,7 +386,7 @@ namespace Emby.Server.Implementations.Library item.Id); } - var parent = item.Parent; + var parent = item.IsOwnedItem ? item.GetOwner() : item.GetParent(); var locationType = item.LocationType; @@ -453,12 +453,28 @@ namespace Emby.Server.Implementations.Library if (parent != null) { - await parent.ValidateChildren(new SimpleProgress(), CancellationToken.None, new MetadataRefreshOptions(_fileSystem), false).ConfigureAwait(false); + var parentFolder = parent as Folder; + if (parentFolder != null) + { + await parentFolder.ValidateChildren(new SimpleProgress(), CancellationToken.None, new MetadataRefreshOptions(_fileSystem), false).ConfigureAwait(false); + } + else + { + await parent.RefreshMetadata(new MetadataRefreshOptions(_fileSystem), CancellationToken.None).ConfigureAwait(false); + } } } else if (parent != null) { - parent.RemoveChild(item); + var parentFolder = parent as Folder; + if (parentFolder != null) + { + parentFolder.RemoveChild(item); + } + else + { + await parent.RefreshMetadata(new MetadataRefreshOptions(_fileSystem), CancellationToken.None).ConfigureAwait(false); + } } ItemRepository.DeleteItem(item.Id, CancellationToken.None); @@ -2604,8 +2620,11 @@ namespace Emby.Server.Implementations.Library { video = dbItem; } - - video.ExtraType = ExtraType.Trailer; + else + { + // item is new + video.ExtraType = ExtraType.Trailer; + } video.TrailerTypes = new List { TrailerType.LocalTrailer }; return video; @@ -2846,13 +2865,6 @@ namespace Emby.Server.Implementations.Library await _providerManagerFactory().SaveImage(item, url, image.Type, imageIndex, CancellationToken.None).ConfigureAwait(false); - var newImage = item.GetImageInfo(image.Type, imageIndex); - - if (newImage != null) - { - newImage.IsPlaceholder = image.IsPlaceholder; - } - await item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None).ConfigureAwait(false); return item.GetImageInfo(image.Type, imageIndex); diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs index c9de3c01b1..0f48ff46b8 100644 --- a/Emby.Server.Implementations/Library/UserManager.cs +++ b/Emby.Server.Implementations/Library/UserManager.cs @@ -518,11 +518,12 @@ namespace Emby.Server.Implementations.Library /// /// The cancellation token. /// Task. - public Task RefreshUsersMetadata(CancellationToken cancellationToken) + public async Task RefreshUsersMetadata(CancellationToken cancellationToken) { - var tasks = Users.Select(user => user.RefreshMetadata(new MetadataRefreshOptions(_fileSystem), cancellationToken)).ToList(); - - return Task.WhenAll(tasks); + foreach (var user in Users) + { + await user.RefreshMetadata(new MetadataRefreshOptions(_fileSystem), cancellationToken).ConfigureAwait(false); + } } /// diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs index 2a2e1886f6..f0578d9efb 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs @@ -42,6 +42,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private async Task RecordFromDirectStreamProvider(IDirectStreamProvider directStreamProvider, string targetFile, TimeSpan duration, Action onStarted, CancellationToken cancellationToken) { + _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(targetFile)); + using (var output = _fileSystem.GetFileStream(targetFile, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) { onStarted(); @@ -76,6 +78,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { _logger.Info("Opened recording stream from tuner provider"); + _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(targetFile)); + using (var output = _fileSystem.GetFileStream(targetFile, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) { onStarted(); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index bd9754f26c..1975a6b019 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1429,14 +1429,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV string liveStreamId = null; - OnRecordingStatusChanged(); - try { var recorder = await GetRecorder().ConfigureAwait(false); var allMediaSources = await GetChannelStreamMediaSources(timer.ChannelId, CancellationToken.None).ConfigureAwait(false); + _logger.Info("Opening recording stream from tuner provider"); var liveStreamInfo = await GetChannelStreamInternal(timer.ChannelId, allMediaSources[0].Id, CancellationToken.None) .ConfigureAwait(false); @@ -1450,23 +1449,20 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV recordPath = EnsureFileUnique(recordPath, timer.Id); _libraryMonitor.ReportFileSystemChangeBeginning(recordPath); - _fileSystem.CreateDirectory(_fileSystem.GetDirectoryName(recordPath)); activeRecordingInfo.Path = recordPath; var duration = recordingEndDate - DateTime.UtcNow; - _logger.Info("Beginning recording. Will record for {0} minutes.", - duration.TotalMinutes.ToString(CultureInfo.InvariantCulture)); + _logger.Info("Beginning recording. Will record for {0} minutes.", duration.TotalMinutes.ToString(CultureInfo.InvariantCulture)); _logger.Info("Writing file to path: " + recordPath); - _logger.Info("Opening recording stream from tuner provider"); - Action onStarted = () => + Action onStarted = async () => { timer.Status = RecordingStatus.InProgress; _timerProvider.AddOrUpdate(timer, false); - SaveRecordingMetadata(timer, recordPath, seriesPath); + await SaveRecordingMetadata(timer, recordPath, seriesPath).ConfigureAwait(false); TriggerRefresh(recordPath); EnforceKeepUpTo(timer, seriesPath); }; @@ -1500,7 +1496,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } TriggerRefresh(recordPath); - _libraryMonitor.ReportFileSystemChangeComplete(recordPath, true); + _libraryMonitor.ReportFileSystemChangeComplete(recordPath, false); ActiveRecordingInfo removed; _activeRecordings.TryRemove(timer.Id, out removed); @@ -1526,17 +1522,29 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { _timerProvider.Delete(timer); } - - OnRecordingStatusChanged(); } private void TriggerRefresh(string path) { + _logger.Debug("Triggering refresh on {0}", path); + var item = GetAffectedBaseItem(_fileSystem.GetDirectoryName(path)); if (item != null) { - item.ChangedExternally(); + _logger.Debug("Refreshing recording parent {0}", item.Path); + + _providerManager.QueueRefresh(item.Id, new MetadataRefreshOptions(_fileSystem) + { + ValidateChildren = true, + RefreshPaths = new List + { + path, + _fileSystem.GetDirectoryName(path), + _fileSystem.GetDirectoryName(_fileSystem.GetDirectoryName(path)) + } + + }, RefreshPriority.High); } } @@ -1544,6 +1552,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { BaseItem item = null; + var parentPath = _fileSystem.GetDirectoryName(path); + while (item == null && !string.IsNullOrEmpty(path)) { item = _libraryManager.FindByPath(path, null); @@ -1553,14 +1563,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV if (item != null) { - // If the item has been deleted find the first valid parent that still exists - while (!_fileSystem.DirectoryExists(item.Path) && !_fileSystem.FileExists(item.Path)) + if (item.GetType() == typeof(Folder) && string.Equals(item.Path, parentPath, StringComparison.OrdinalIgnoreCase)) { - item = item.GetParent(); - - if (item == null) + var parentItem = item.GetParent(); + if (parentItem != null && !(parentItem is AggregateFolder)) { - break; + item = parentItem; } } } @@ -1568,14 +1576,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV return item; } - private void OnRecordingStatusChanged() - { - EventHelper.FireEventIfNotNull(RecordingStatusChanged, this, new RecordingStatusChangedEventArgs - { - - }, _logger); - } - private async void EnforceKeepUpTo(TimerInfo timer, string seriesPath) { if (string.IsNullOrWhiteSpace(timer.SeriesTimerId)) @@ -1960,7 +1960,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } } - private async void SaveRecordingMetadata(TimerInfo timer, string recordingPath, string seriesPath) + private async Task SaveRecordingMetadata(TimerInfo timer, string recordingPath, string seriesPath) { try { diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 870a3b4937..38d2fd3c64 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -843,8 +843,7 @@ namespace Emby.Server.Implementations.LiveTv item.SetImage(new ItemImageInfo { Path = info.ImagePath, - Type = ImageType.Primary, - IsPlaceholder = true + Type = ImageType.Primary }, 0); } else if (!string.IsNullOrWhiteSpace(info.ImageUrl)) @@ -852,8 +851,7 @@ namespace Emby.Server.Implementations.LiveTv item.SetImage(new ItemImageInfo { Path = info.ImageUrl, - Type = ImageType.Primary, - IsPlaceholder = true + Type = ImageType.Primary }, 0); } } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs index 4dcbc4b54c..af064755d0 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHttpStream.cs @@ -134,7 +134,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } _liveStreamTaskCompletionSource.TrySetResult(true); - //await DeleteTempFile(_tempFilePath).ConfigureAwait(false); + await DeleteTempFile(_tempFilePath).ConfigureAwait(false); }); } diff --git a/Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs b/Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs index 525df03504..36e8b4dd89 100644 --- a/Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs +++ b/Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs @@ -53,7 +53,7 @@ namespace Emby.Server.Implementations.Playlists return subItem; } - var parent = subItem.GetParent(); + var parent = subItem.IsOwnedItem ? subItem.GetOwner() : subItem.GetParent(); if (parent != null && parent.HasImage(ImageType.Primary)) { diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs index 2105ef9079..00fac1eabd 100644 --- a/MediaBrowser.Controller/Entities/AggregateFolder.cs +++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs @@ -137,7 +137,7 @@ namespace MediaBrowser.Controller.Entities { FileInfo = FileSystem.GetDirectoryInfo(path), Path = path, - Parent = Parent + Parent = GetParent() as Folder }; // Gather child folder and files diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 4416c5e916..502ba6c60e 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -97,7 +97,7 @@ namespace MediaBrowser.Controller.Entities public string Tagline { get; set; } [IgnoreDataMember] - public ItemImageInfo[] ImageInfos { get; set; } + public virtual ItemImageInfo[] ImageInfos { get; set; } [IgnoreDataMember] public bool IsVirtualItem { get; set; } @@ -216,6 +216,9 @@ namespace MediaBrowser.Controller.Entities [IgnoreDataMember] public Guid Id { get; set; } + [IgnoreDataMember] + public Guid OwnerId { get; set; } + /// /// Gets or sets a value indicating whether this instance is hd. /// @@ -321,12 +324,31 @@ namespace MediaBrowser.Controller.Entities { get { + if (OwnerId != Guid.Empty) + { + return true; + } + + // legacy + // Local trailer, special feature, theme video, etc. // An item that belongs to another item but is not part of the Parent-Child tree - return !IsFolder && ParentId == Guid.Empty && LocationType == LocationType.FileSystem; + // This is a hack for now relying on ExtraType. Eventually we may need to persist this + if (ParentId == Guid.Empty && !IsFolder && LocationType == LocationType.FileSystem) + { + return true; + } + + return false; } } + public BaseItem GetOwner() + { + var ownerId = OwnerId; + return ownerId == Guid.Empty ? null : LibraryManager.GetItemById(ownerId); + } + /// /// Gets or sets the type of the location. /// @@ -727,17 +749,12 @@ namespace MediaBrowser.Controller.Entities ParentId = parent == null ? Guid.Empty : parent.Id; } - [IgnoreDataMember] - public IEnumerable Parents - { - get { return GetParents().OfType(); } - } - public BaseItem GetParent() { - if (ParentId != Guid.Empty) + var parentId = ParentId; + if (parentId != Guid.Empty) { - return LibraryManager.GetItemById(ParentId); + return LibraryManager.GetItemById(parentId); } return null; @@ -779,11 +796,13 @@ namespace MediaBrowser.Controller.Entities { get { - if (ParentId == Guid.Empty) + var parentId = ParentId; + + if (parentId == Guid.Empty) { return null; } - return ParentId; + return parentId; } } @@ -1002,8 +1021,11 @@ namespace MediaBrowser.Controller.Entities { audio = dbItem; } - - audio.ExtraType = MediaBrowser.Model.Entities.ExtraType.ThemeSong; + else + { + // item is new + audio.ExtraType = MediaBrowser.Model.Entities.ExtraType.ThemeSong; + } return audio; @@ -1032,8 +1054,11 @@ namespace MediaBrowser.Controller.Entities { item = dbItem; } - - item.ExtraType = MediaBrowser.Model.Entities.ExtraType.ThemeVideo; + else + { + // item is new + item.ExtraType = MediaBrowser.Model.Entities.ExtraType.ThemeVideo; + } return item; @@ -1178,8 +1203,25 @@ namespace MediaBrowser.Controller.Entities var newItemIds = newItems.Select(i => i.Id).ToArray(); var itemsChanged = !item.LocalTrailerIds.SequenceEqual(newItemIds); + var ownerId = item.Id; - var tasks = newItems.Select(i => RefreshMetadataForOwnedItem(i, true, options, cancellationToken)); + var tasks = newItems.Select(i => + { + var subOptions = new MetadataRefreshOptions(options); + + if (!i.ExtraType.HasValue || + i.ExtraType.Value != Model.Entities.ExtraType.Trailer || + i.OwnerId != ownerId || + i.ParentId != Guid.Empty) + { + i.ExtraType = Model.Entities.ExtraType.Trailer; + i.OwnerId = ownerId; + i.ParentId = Guid.Empty; + subOptions.ForceSave = true; + } + + return RefreshMetadataForOwnedItem(i, true, subOptions, cancellationToken); + }); await Task.WhenAll(tasks).ConfigureAwait(false); @@ -1196,13 +1238,20 @@ namespace MediaBrowser.Controller.Entities var themeVideosChanged = !item.ThemeVideoIds.SequenceEqual(newThemeVideoIds); + var ownerId = item.Id; + var tasks = newThemeVideos.Select(i => { var subOptions = new MetadataRefreshOptions(options); - if (!i.IsThemeMedia) + if (!i.ExtraType.HasValue || + i.ExtraType.Value != Model.Entities.ExtraType.ThemeVideo || + i.OwnerId != ownerId || + i.ParentId != Guid.Empty) { - i.ExtraType = MediaBrowser.Model.Entities.ExtraType.ThemeVideo; + i.ExtraType = Model.Entities.ExtraType.ThemeVideo; + i.OwnerId = ownerId; + i.ParentId = Guid.Empty; subOptions.ForceSave = true; } @@ -1226,13 +1275,20 @@ namespace MediaBrowser.Controller.Entities var themeSongsChanged = !item.ThemeSongIds.SequenceEqual(newThemeSongIds); + var ownerId = item.Id; + var tasks = newThemeSongs.Select(i => { var subOptions = new MetadataRefreshOptions(options); - if (!i.IsThemeMedia) + if (!i.ExtraType.HasValue || + i.ExtraType.Value != Model.Entities.ExtraType.ThemeSong || + i.OwnerId != ownerId || + i.ParentId != Guid.Empty) { - i.ExtraType = MediaBrowser.Model.Entities.ExtraType.ThemeSong; + i.ExtraType = Model.Entities.ExtraType.ThemeSong; + i.OwnerId = ownerId; + i.ParentId = Guid.Empty; subOptions.ForceSave = true; } @@ -1868,7 +1924,6 @@ namespace MediaBrowser.Controller.Entities { existingImage.Path = image.Path; existingImage.DateModified = image.DateModified; - existingImage.IsPlaceholder = image.IsPlaceholder; } else @@ -1902,7 +1957,6 @@ namespace MediaBrowser.Controller.Entities image.Path = file.FullName; image.DateModified = imageInfo.DateModified; - image.IsPlaceholder = false; } } @@ -2359,6 +2413,14 @@ namespace MediaBrowser.Controller.Entities newOptions.ForceSave = true; } + //var parentId = Id; + //if (!video.IsOwnedItem || video.ParentId != parentId) + //{ + // video.IsOwnedItem = true; + // video.ParentId = parentId; + // newOptions.ForceSave = true; + //} + if (video == null) { return Task.FromResult(true); diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs index 537beb26b6..a83e084db5 100644 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs @@ -280,7 +280,7 @@ namespace MediaBrowser.Controller.Entities { FileInfo = FileSystem.GetDirectoryInfo(path), Path = path, - Parent = Parent, + Parent = GetParent() as Folder, CollectionType = CollectionType }; diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 2e741a8c44..6d88f70152 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -378,6 +378,7 @@ namespace MediaBrowser.Controller.Entities cancellationToken.ThrowIfCancellationRequested(); var validChildren = new List(); + var validChildrenNeedGeneration = false; var allLibraryPaths = LibraryManager .GetVirtualFolders() @@ -474,11 +475,7 @@ namespace MediaBrowser.Controller.Entities } else { - if (recursive || refreshChildMetadata) - { - // used below - validChildren = Children.ToList(); - } + validChildrenNeedGeneration = true; } progress.Report(10); @@ -502,6 +499,12 @@ namespace MediaBrowser.Controller.Entities ProviderManager.OnRefreshProgress(folder, newPct); }); + if (validChildrenNeedGeneration) + { + validChildren = Children.ToList(); + validChildrenNeedGeneration = false; + } + await ValidateSubFolders(validChildren.OfType().ToList(), directoryService, innerProgress, cancellationToken).ConfigureAwait(false); } } @@ -536,6 +539,12 @@ namespace MediaBrowser.Controller.Entities } else { + if (validChildrenNeedGeneration) + { + validChildren = Children.ToList(); + validChildrenNeedGeneration = false; + } + await RefreshMetadataRecursive(validChildren, refreshOptions, recursive, innerProgress, cancellationToken); } } @@ -565,7 +574,7 @@ namespace MediaBrowser.Controller.Entities }); await RefreshChildMetadata(child, refreshOptions, recursive && child.IsFolder, innerProgress, cancellationToken) - .ConfigureAwait(false); + .ConfigureAwait(false); } numComplete++; @@ -588,7 +597,10 @@ namespace MediaBrowser.Controller.Entities } else { - await child.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); + if (refreshOptions.RefreshItem(child)) + { + await child.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); + } if (recursive) { @@ -1196,11 +1208,21 @@ namespace MediaBrowser.Controller.Entities /// Gets the linked children. /// /// IEnumerable{BaseItem}. - public IEnumerable GetLinkedChildren() + public List GetLinkedChildren() { - return LinkedChildren - .Select(GetLinkedChild) - .Where(i => i != null); + var linkedChildren = LinkedChildren; + var list = new List(linkedChildren.Length); + + foreach (var i in linkedChildren) + { + var child = GetLinkedChild(i); + + if (child != null) + { + list.Add(child); + } + } + return list; } protected virtual bool FilterLinkedChildrenPerUser @@ -1211,16 +1233,19 @@ namespace MediaBrowser.Controller.Entities } } - public IEnumerable GetLinkedChildren(User user) + public List GetLinkedChildren(User user) { if (!FilterLinkedChildrenPerUser || user == null) { return GetLinkedChildren(); } - if (LinkedChildren.Length == 0) + var linkedChildren = LinkedChildren; + var list = new List(linkedChildren.Length); + + if (linkedChildren.Length == 0) { - return new List(); + return list; } var allUserRootChildren = user.RootFolder.Children.OfType().ToList(); @@ -1231,37 +1256,43 @@ namespace MediaBrowser.Controller.Entities .Select(i => i.Id) .ToList(); - return LinkedChildren - .Select(i => + foreach (var i in linkedChildren) + { + var child = GetLinkedChild(i); + + if (child == null) { - var child = GetLinkedChild(i); + continue; + } + + var childOwner = child.IsOwnedItem ? (child.GetOwner() ?? child) : child; - if (child != null) + if (childOwner != null) + { + var childLocationType = childOwner.LocationType; + if (childLocationType == LocationType.Remote || childLocationType == LocationType.Virtual) { - var childLocationType = child.LocationType; - if (childLocationType == LocationType.Remote || childLocationType == LocationType.Virtual) + if (!childOwner.IsVisibleStandalone(user)) { - if (!child.IsVisibleStandalone(user)) - { - return null; - } + continue; } - else if (childLocationType == LocationType.FileSystem) - { - var itemCollectionFolderIds = - LibraryManager.GetCollectionFolders(child, allUserRootChildren) - .Select(f => f.Id).ToList(); + } + else if (childLocationType == LocationType.FileSystem) + { + var itemCollectionFolderIds = + LibraryManager.GetCollectionFolders(childOwner, allUserRootChildren).Select(f => f.Id); - if (!itemCollectionFolderIds.Any(collectionFolderIds.Contains)) - { - return null; - } + if (!itemCollectionFolderIds.Any(collectionFolderIds.Contains)) + { + continue; } } + } + + list.Add(child); + } - return child; - }) - .Where(i => i != null); + return list; } /// diff --git a/MediaBrowser.Controller/Entities/IHasTrailers.cs b/MediaBrowser.Controller/Entities/IHasTrailers.cs index 8686c802ab..07dde37894 100644 --- a/MediaBrowser.Controller/Entities/IHasTrailers.cs +++ b/MediaBrowser.Controller/Entities/IHasTrailers.cs @@ -5,7 +5,7 @@ using System.Linq; namespace MediaBrowser.Controller.Entities { - public interface IHasTrailers : IHasProviderIds + public interface IHasTrailers : IHasMetadata { /// /// Gets or sets the remote trailers. diff --git a/MediaBrowser.Controller/Entities/ItemImageInfo.cs b/MediaBrowser.Controller/Entities/ItemImageInfo.cs index 672595db84..6b2d2392dc 100644 --- a/MediaBrowser.Controller/Entities/ItemImageInfo.cs +++ b/MediaBrowser.Controller/Entities/ItemImageInfo.cs @@ -24,12 +24,6 @@ namespace MediaBrowser.Controller.Entities /// The date modified. public DateTime DateModified { get; set; } - /// - /// Gets or sets a value indicating whether this instance is placeholder. - /// - /// true if this instance is placeholder; otherwise, false. - public bool IsPlaceholder { get; set; } - [IgnoreDataMember] public bool IsLocalFile { diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs index 3a41709fed..2e0e019443 100644 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs @@ -81,7 +81,20 @@ namespace MediaBrowser.Controller.Entities.Movies var itemsChanged = !SpecialFeatureIds.SequenceEqual(newItemIds); - var tasks = newItems.Select(i => RefreshMetadataForOwnedItem(i, false, options, cancellationToken)); + var ownerId = Id; + + var tasks = newItems.Select(i => + { + var subOptions = new MetadataRefreshOptions(options); + + if (i.OwnerId != ownerId) + { + i.OwnerId = ownerId; + subOptions.ForceSave = true; + } + + return RefreshMetadataForOwnedItem(i, false, subOptions, cancellationToken); + }); await Task.WhenAll(tasks).ConfigureAwait(false); diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 60d2624fa9..5931c32e1b 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -347,7 +347,10 @@ namespace MediaBrowser.Controller.Entities.TV cancellationToken.ThrowIfCancellationRequested(); - await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); + if (refreshOptions.RefreshItem(item)) + { + await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); + } numComplete++; double percent = numComplete; @@ -382,7 +385,10 @@ namespace MediaBrowser.Controller.Entities.TV if (!skipItem) { - await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); + if (refreshOptions.RefreshItem(item)) + { + await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); + } } numComplete++; diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs index cca3091c15..4aa1311e1f 100644 --- a/MediaBrowser.Controller/Entities/User.cs +++ b/MediaBrowser.Controller/Entities/User.cs @@ -37,6 +37,9 @@ namespace MediaBrowser.Controller.Entities public UserLinkType? ConnectLinkType { get; set; } public string ConnectAccessKey { get; set; } + // Strictly to remove IgnoreDataMember + public override ItemImageInfo[] ImageInfos { get => base.ImageInfos; set => base.ImageInfos = value; } + /// /// Gets or sets the path. /// diff --git a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs index 86cef628e0..0df2370bd3 100644 --- a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs +++ b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs @@ -1,5 +1,7 @@ -using System.Linq; - +using System; +using System.Collections.Generic; +using System.Linq; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.IO; using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; @@ -20,6 +22,8 @@ namespace MediaBrowser.Controller.Providers public MetadataRefreshMode MetadataRefreshMode { get; set; } public RemoteSearchResult SearchResult { get; set; } + public List RefreshPaths { get; set; } + public bool ForceSave { get; set; } public MetadataRefreshOptions(IFileSystem fileSystem) @@ -44,6 +48,26 @@ namespace MediaBrowser.Controller.Providers ReplaceAllImages = copy.ReplaceAllImages; ReplaceImages = copy.ReplaceImages.ToList(); SearchResult = copy.SearchResult; + + if (copy.RefreshPaths != null && copy.RefreshPaths.Count > 0) + { + if (RefreshPaths == null) + { + RefreshPaths = new List(); + } + + RefreshPaths.AddRange(copy.RefreshPaths); + } + } + + public bool RefreshItem(BaseItem item) + { + if (RefreshPaths != null && RefreshPaths.Count > 0) + { + return RefreshPaths.Contains(item.Path ?? string.Empty, StringComparer.OrdinalIgnoreCase); + } + + return true; } } } diff --git a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs index 2c2f22e867..a70a1066d7 100644 --- a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs +++ b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs @@ -33,7 +33,6 @@ namespace MediaBrowser.Model.LiveTv MediaLocationsCreated = new string[] { }; RecordingEncodingFormat = "mkv"; RecordingPostProcessorArguments = "\"{path}\""; - EnableRecordingEncoding = true; } } diff --git a/MediaBrowser.Providers/Manager/GenericPriorityQueue.cs b/MediaBrowser.Providers/Manager/GenericPriorityQueue.cs index e245476146..0e6c073577 100644 --- a/MediaBrowser.Providers/Manager/GenericPriorityQueue.cs +++ b/MediaBrowser.Providers/Manager/GenericPriorityQueue.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; @@ -66,9 +67,7 @@ namespace Priority_Queue /// Removes every node from the queue. /// O(n) (So, don't do this often!) /// -#if NET_VERSION_4_5 [MethodImpl(MethodImplOptions.AggressiveInlining)] -#endif public void Clear() { Array.Clear(_nodes, 1, _numNodes); @@ -78,9 +77,7 @@ namespace Priority_Queue /// /// Returns (in O(1)!) whether the given node is in the queue. O(1) /// -#if NET_VERSION_4_5 [MethodImpl(MethodImplOptions.AggressiveInlining)] -#endif public bool Contains(TItem node) { #if DEBUG @@ -103,9 +100,7 @@ namespace Priority_Queue /// If the node is already enqueued, the result is undefined. /// O(log n) /// -#if NET_VERSION_4_5 [MethodImpl(MethodImplOptions.AggressiveInlining)] -#endif public void Enqueue(TItem node, TPriority priority) { #if DEBUG @@ -131,9 +126,7 @@ namespace Priority_Queue CascadeUp(_nodes[_numNodes]); } -#if NET_VERSION_4_5 [MethodImpl(MethodImplOptions.AggressiveInlining)] -#endif private void Swap(TItem node1, TItem node2) { //Swap the nodes @@ -164,9 +157,7 @@ namespace Priority_Queue } } -#if NET_VERSION_4_5 [MethodImpl(MethodImplOptions.AggressiveInlining)] -#endif private void CascadeDown(TItem node) { //aka Heapify-down @@ -228,9 +219,7 @@ namespace Priority_Queue /// Returns true if 'higher' has higher priority than 'lower', false otherwise. /// Note that calling HasHigherPriority(node, node) (ie. both arguments the same node) will return false /// -#if NET_VERSION_4_5 [MethodImpl(MethodImplOptions.AggressiveInlining)] -#endif private bool HasHigherPriority(TItem higher, TItem lower) { var cmp = higher.Priority.CompareTo(lower.Priority); @@ -319,9 +308,7 @@ namespace Priority_Queue /// Calling this method on a node not in the queue results in undefined behavior /// O(log n) /// -#if NET_VERSION_4_5 [MethodImpl(MethodImplOptions.AggressiveInlining)] -#endif public void UpdatePriority(TItem node, TPriority priority) { #if DEBUG diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs index e62ce0225d..a6d4d4c334 100644 --- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs +++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs @@ -206,8 +206,7 @@ namespace MediaBrowser.Providers.Manager { var image = item.GetImageInfo(type, 0); - // if it's a placeholder image then pretend like it's not there so that we can replace it - return image != null && !image.IsPlaceholder; + return image != null; } /// @@ -547,7 +546,7 @@ namespace MediaBrowser.Providers.Manager switch (type) { case ImageType.Primary: - return !(item is Movie || item is Series || item is Game); + return true; default: return true; } diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs index ae029cc594..b93f783418 100644 --- a/MediaBrowser.Providers/Manager/MetadataService.cs +++ b/MediaBrowser.Providers/Manager/MetadataService.cs @@ -262,8 +262,7 @@ namespace MediaBrowser.Providers.Manager personEntity.SetImage(new ItemImageInfo { Path = imageUrl, - Type = ImageType.Primary, - IsPlaceholder = true + Type = ImageType.Primary }, 0); } diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs index 333f3d5932..a9aa71bfa4 100644 --- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs @@ -146,6 +146,11 @@ namespace MediaBrowser.Providers.MediaInfo return _cachedTask; } + if (!item.IsCompleteMedia) + { + return _cachedTask; + } + if (item.IsShortcut) { FetchShortcutInfo(item); diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs index f666d8b7ff..9b0d29cf04 100644 --- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs +++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs @@ -133,7 +133,7 @@ namespace MediaBrowser.Providers.MediaInfo { var video = item as Video; - if (item.LocationType == LocationType.FileSystem && video != null && !video.IsPlaceHolder && !video.IsShortcut) + if (item.LocationType == LocationType.FileSystem && video != null && !video.IsPlaceHolder && !video.IsShortcut && video.IsCompleteMedia) { return true; } -- cgit v1.2.3