diff options
Diffstat (limited to 'MediaBrowser.Controller')
45 files changed, 597 insertions, 296 deletions
diff --git a/MediaBrowser.Controller/Channels/Channel.cs b/MediaBrowser.Controller/Channels/Channel.cs index f74c01994..54faa1443 100644 --- a/MediaBrowser.Controller/Channels/Channel.cs +++ b/MediaBrowser.Controller/Channels/Channel.cs @@ -32,14 +32,6 @@ namespace MediaBrowser.Controller.Channels return base.IsVisible(user); } - public override double? GetDefaultPrimaryImageAspectRatio() - { - double value = 16; - value /= 9; - - return value; - } - [IgnoreDataMember] public override bool SupportsInheritedParentImages { diff --git a/MediaBrowser.Controller/Channels/IChannelManager.cs b/MediaBrowser.Controller/Channels/IChannelManager.cs index 46e55a21c..37fc892b3 100644 --- a/MediaBrowser.Controller/Channels/IChannelManager.cs +++ b/MediaBrowser.Controller/Channels/IChannelManager.cs @@ -117,14 +117,13 @@ namespace MediaBrowser.Controller.Channels /// </summary> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>BaseItemDto.</returns> - Task<Folder> GetInternalChannelFolder(CancellationToken cancellationToken); + Folder GetInternalChannelFolder(CancellationToken cancellationToken); /// <summary> /// Gets the channel folder. /// </summary> /// <param name="userId">The user identifier.</param> /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>BaseItemDto.</returns> - Task<BaseItemDto> GetChannelFolder(string userId, CancellationToken cancellationToken); + BaseItemDto GetChannelFolder(string userId, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Controller/Devices/IDeviceManager.cs b/MediaBrowser.Controller/Devices/IDeviceManager.cs index 2846bcfc6..676db09aa 100644 --- a/MediaBrowser.Controller/Devices/IDeviceManager.cs +++ b/MediaBrowser.Controller/Devices/IDeviceManager.cs @@ -28,7 +28,7 @@ namespace MediaBrowser.Controller.Devices /// <param name="appVersion">The application version.</param> /// <param name="usedByUserId">The used by user identifier.</param> /// <returns>Task.</returns> - Task<DeviceInfo> RegisterDevice(string reportedId, string name, string appName, string appVersion, string usedByUserId); + DeviceInfo RegisterDevice(string reportedId, string name, string appName, string appVersion, string usedByUserId); /// <summary> /// Saves the capabilities. @@ -36,7 +36,7 @@ namespace MediaBrowser.Controller.Devices /// <param name="reportedId">The reported identifier.</param> /// <param name="capabilities">The capabilities.</param> /// <returns>Task.</returns> - Task SaveCapabilities(string reportedId, ClientCapabilities capabilities); + void SaveCapabilities(string reportedId, ClientCapabilities capabilities); /// <summary> /// Gets the capabilities. @@ -58,7 +58,7 @@ namespace MediaBrowser.Controller.Devices /// <param name="id">The identifier.</param> /// <param name="options">The options.</param> /// <returns>Task.</returns> - Task UpdateDeviceInfo(string id, DeviceOptions options); + void UpdateDeviceInfo(string id, DeviceOptions options); /// <summary> /// Gets the devices. @@ -67,12 +67,7 @@ namespace MediaBrowser.Controller.Devices /// <returns>IEnumerable<DeviceInfo>.</returns> QueryResult<DeviceInfo> GetDevices(DeviceQuery query); - /// <summary> - /// Deletes the device. - /// </summary> - /// <param name="id">The identifier.</param> - /// <returns>Task.</returns> - Task DeleteDevice(string id); + void DeleteDevice(string id); /// <summary> /// Gets the upload history. diff --git a/MediaBrowser.Controller/Devices/IDeviceRepository.cs b/MediaBrowser.Controller/Devices/IDeviceRepository.cs index 736504da3..b9ebbb6c7 100644 --- a/MediaBrowser.Controller/Devices/IDeviceRepository.cs +++ b/MediaBrowser.Controller/Devices/IDeviceRepository.cs @@ -1,7 +1,6 @@ using MediaBrowser.Model.Devices; using MediaBrowser.Model.Session; using System.Collections.Generic; -using System.Threading.Tasks; namespace MediaBrowser.Controller.Devices { @@ -12,7 +11,7 @@ namespace MediaBrowser.Controller.Devices /// </summary> /// <param name="device">The device.</param> /// <returns>Task.</returns> - Task SaveDevice(DeviceInfo device); + void SaveDevice(DeviceInfo device); /// <summary> /// Saves the capabilities. @@ -20,7 +19,7 @@ namespace MediaBrowser.Controller.Devices /// <param name="id">The identifier.</param> /// <param name="capabilities">The capabilities.</param> /// <returns>Task.</returns> - Task SaveCapabilities(string id, ClientCapabilities capabilities); + void SaveCapabilities(string id, ClientCapabilities capabilities); /// <summary> /// Gets the capabilities. @@ -36,18 +35,14 @@ namespace MediaBrowser.Controller.Devices /// <returns>DeviceInfo.</returns> DeviceInfo GetDevice(string id); - /// <summary> - /// Gets the devices. - /// </summary> - /// <returns>IEnumerable<DeviceInfo>.</returns> - IEnumerable<DeviceInfo> GetDevices(); + List<DeviceInfo> GetDevices(); /// <summary> /// Deletes the device. /// </summary> /// <param name="id">The identifier.</param> /// <returns>Task.</returns> - Task DeleteDevice(string id); + void DeleteDevice(string id); /// <summary> /// Gets the upload history. diff --git a/MediaBrowser.Controller/Dlna/IEventManager.cs b/MediaBrowser.Controller/Dlna/IEventManager.cs index 8c91bd889..3af357a17 100644 --- a/MediaBrowser.Controller/Dlna/IEventManager.cs +++ b/MediaBrowser.Controller/Dlna/IEventManager.cs @@ -12,7 +12,7 @@ namespace MediaBrowser.Controller.Dlna /// <summary> /// Renews the event subscription. /// </summary> - EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string requestedTimeoutString); + EventSubscriptionResponse RenewEventSubscription(string subscriptionId, string notificationType, string requestedTimeoutString, string callbackUrl); /// <summary> /// Creates the event subscription. diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs index 542fa5e08..0bc92ac7e 100644 --- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs +++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs @@ -26,21 +26,16 @@ namespace MediaBrowser.Controller.Drawing /// <value>The image enhancers.</value> IImageEnhancer[] ImageEnhancers { get; } + ImageSize GetImageSize(string path); + /// <summary> /// Gets the size of the image. /// </summary> /// <param name="info">The information.</param> /// <returns>ImageSize.</returns> - ImageSize GetImageSize(ItemImageInfo info); + ImageSize GetImageSize(BaseItem item, ItemImageInfo info); - ImageSize GetImageSize(ItemImageInfo info, bool allowSlowMethods); - - /// <summary> - /// Gets the size of the image. - /// </summary> - /// <param name="path">The path.</param> - /// <returns>ImageSize.</returns> - ImageSize GetImageSize(string path); + ImageSize GetImageSize(BaseItem item, ItemImageInfo info, bool allowSlowMethods, bool updateItem); /// <summary> /// Adds the parts. diff --git a/MediaBrowser.Controller/Dto/IDtoService.cs b/MediaBrowser.Controller/Dto/IDtoService.cs index c0217330d..5ba6e036e 100644 --- a/MediaBrowser.Controller/Dto/IDtoService.cs +++ b/MediaBrowser.Controller/Dto/IDtoService.cs @@ -23,14 +23,14 @@ namespace MediaBrowser.Controller.Dto /// </summary> /// <param name="dto">The dto.</param> /// <param name="item">The item.</param> - void AttachPrimaryImageAspectRatio(IItemDto dto, IHasMetadata item); + void AttachPrimaryImageAspectRatio(IItemDto dto, BaseItem item); /// <summary> /// Gets the primary image aspect ratio. /// </summary> /// <param name="item">The item.</param> /// <returns>System.Nullable<System.Double>.</returns> - double? GetPrimaryImageAspectRatio(IHasMetadata item); + double? GetPrimaryImageAspectRatio(BaseItem item); /// <summary> /// Gets the base item dto. diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index 02a9f15a9..16fd75d2e 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs @@ -61,6 +61,12 @@ namespace MediaBrowser.Controller.Entities.Audio } [IgnoreDataMember] + public override bool SupportsPeople + { + get { return false; } + } + + [IgnoreDataMember] public override bool SupportsAddingToPlaylist { get { return true; } diff --git a/MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs b/MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs index d2b4569ba..1b717b900 100644 --- a/MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs +++ b/MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs @@ -1,8 +1,9 @@ -using MediaBrowser.Model.Serialization; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Serialization; namespace MediaBrowser.Controller.Entities.Audio { - public class AudioPodcast : Audio + public class AudioPodcast : Audio, IHasLookupInfo<SongInfo> { [IgnoreDataMember] public override bool SupportsPositionTicksResume @@ -13,6 +14,15 @@ namespace MediaBrowser.Controller.Entities.Audio } } + [IgnoreDataMember] + public override bool SupportsPlayedStatus + { + get + { + return true; + } + } + public override double? GetDefaultPrimaryImageAspectRatio() { return 1; diff --git a/MediaBrowser.Controller/Entities/AudioBook.cs b/MediaBrowser.Controller/Entities/AudioBook.cs index 1bdcfb881..374bb21f7 100644 --- a/MediaBrowser.Controller/Entities/AudioBook.cs +++ b/MediaBrowser.Controller/Entities/AudioBook.cs @@ -1,11 +1,12 @@ using System; +using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Entities { - public class AudioBook : Audio.Audio, IHasSeries + public class AudioBook : Audio.Audio, IHasSeries, IHasLookupInfo<SongInfo> { [IgnoreDataMember] public override bool SupportsPositionTicksResume @@ -50,12 +51,6 @@ namespace MediaBrowser.Controller.Entities return null; } - [IgnoreDataMember] - public override bool EnableRefreshOnDateModifiedChange - { - get { return true; } - } - public Guid? FindSeriesId() { return SeriesId; diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 502ba6c60..89d48ff90 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -477,14 +477,36 @@ namespace MediaBrowser.Controller.Entities locationType != LocationType.Virtual; } - public virtual bool IsAuthorizedToDelete(User user) + public virtual bool IsAuthorizedToDelete(User user, List<Folder> allCollectionFolders) { - return user.Policy.EnableContentDeletion; + if (user.Policy.EnableContentDeletion) + { + return true; + } + + var allowed = user.Policy.EnableContentDeletionFromFolders; + var collectionFolders = LibraryManager.GetCollectionFolders(this, allCollectionFolders); + + foreach (var folder in collectionFolders) + { + if (allowed.Contains(folder.Id.ToString("N"), StringComparer.OrdinalIgnoreCase)) + { + return true; + } + } + + return false; + } + + public bool CanDelete(User user, List<Folder> allCollectionFolders) + { + return CanDelete() && IsAuthorizedToDelete(user, allCollectionFolders); } public bool CanDelete(User user) { - return CanDelete() && IsAuthorizedToDelete(user); + var allCollectionFolders = LibraryManager.GetUserRootFolder().Children.OfType<Folder>().ToList(); + return CanDelete(user, allCollectionFolders); } public virtual bool CanDownload() @@ -1142,7 +1164,7 @@ namespace MediaBrowser.Controller.Entities [IgnoreDataMember] public virtual bool SupportsPeople { - get { return true; } + get { return false; } } [IgnoreDataMember] @@ -1281,8 +1303,8 @@ namespace MediaBrowser.Controller.Entities { var subOptions = new MetadataRefreshOptions(options); - if (!i.ExtraType.HasValue || - i.ExtraType.Value != Model.Entities.ExtraType.ThemeSong || + if (!i.ExtraType.HasValue || + i.ExtraType.Value != Model.Entities.ExtraType.ThemeSong || i.OwnerId != ownerId || i.ParentId != Guid.Empty) { @@ -1356,14 +1378,20 @@ namespace MediaBrowser.Controller.Entities internal virtual bool IsValidFromResolver(BaseItem newItem) { - var current = this; + return true; + } - if (current.IsInMixedFolder != newItem.IsInMixedFolder) + internal virtual ItemUpdateType UpdateFromResolvedItem(BaseItem newItem) + { + var updateType = ItemUpdateType.None; + + if (IsInMixedFolder != newItem.IsInMixedFolder) { - return false; + IsInMixedFolder = newItem.IsInMixedFolder; + updateType |= ItemUpdateType.MetadataImport; } - return true; + return updateType; } public void AfterMetadataRefresh() @@ -1924,6 +1952,8 @@ namespace MediaBrowser.Controller.Entities { existingImage.Path = image.Path; existingImage.DateModified = image.DateModified; + existingImage.Width = image.Width; + existingImage.Height = image.Height; } else @@ -1966,14 +1996,14 @@ namespace MediaBrowser.Controller.Entities /// <param name="type">The type.</param> /// <param name="index">The index.</param> /// <returns>Task.</returns> - public Task DeleteImage(ImageType type, int index) + public void DeleteImage(ImageType type, int index) { var info = GetImageInfo(type, index); if (info == null) { // Nothing to do - return Task.FromResult(true); + return; } // Remove it from the item @@ -1984,7 +2014,7 @@ namespace MediaBrowser.Controller.Entities FileSystem.DeleteFile(info.Path); } - return UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); + UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); } public void RemoveImage(ItemImageInfo image) @@ -1997,9 +2027,9 @@ namespace MediaBrowser.Controller.Entities ImageInfos = ImageInfos.Except(deletedImages).ToArray(); } - public virtual Task UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken) + public virtual void UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken) { - return LibraryManager.UpdateItem(this, updateReason, cancellationToken); + LibraryManager.UpdateItem(this, updateReason, cancellationToken); } /// <summary> @@ -2209,7 +2239,7 @@ namespace MediaBrowser.Controller.Entities return type == ImageType.Backdrop || type == ImageType.Screenshot || type == ImageType.Chapter; } - public Task SwapImages(ImageType type, int index1, int index2) + public void SwapImages(ImageType type, int index1, int index2) { if (!AllowsMultipleImages(type)) { @@ -2222,13 +2252,13 @@ namespace MediaBrowser.Controller.Entities if (info1 == null || info2 == null) { // Nothing to do - return Task.FromResult(true); + return; } if (!info1.IsLocalFile || !info2.IsLocalFile) { // TODO: Not supported yet - return Task.FromResult(true); + return; } var path1 = info1.Path; @@ -2240,7 +2270,12 @@ namespace MediaBrowser.Controller.Entities info1.DateModified = FileSystem.GetLastWriteTimeUtc(info1.Path); info2.DateModified = FileSystem.GetLastWriteTimeUtc(info2.Path); - return UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); + info1.Width = 0; + info1.Height = 0; + info2.Width = 0; + info2.Height = 0; + + UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); } public virtual bool IsPlayed(User user) @@ -2526,15 +2561,6 @@ namespace MediaBrowser.Controller.Entities return LibraryManager.DeleteItem(this, options); } - public virtual Task OnFileDeleted() - { - // Remove from database - return Delete(new DeleteOptions - { - DeleteFileLocation = false - }); - } - public virtual List<ExternalUrl> GetRelatedUrls() { return new List<ExternalUrl>(); diff --git a/MediaBrowser.Controller/Entities/Book.cs b/MediaBrowser.Controller/Entities/Book.cs index 9b1a52f83..45e3915ce 100644 --- a/MediaBrowser.Controller/Entities/Book.cs +++ b/MediaBrowser.Controller/Entities/Book.cs @@ -38,12 +38,6 @@ namespace MediaBrowser.Controller.Entities return SeriesPresentationUniqueKey; } - [IgnoreDataMember] - public override bool EnableRefreshOnDateModifiedChange - { - get { return true; } - } - public Guid? FindSeriesId() { return SeriesId; diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 6d88f7015..ce7145a79 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -328,11 +328,6 @@ namespace MediaBrowser.Controller.Entities return dictionary; } - private bool IsValidFromResolver(BaseItem current, BaseItem newItem) - { - return current.IsValidFromResolver(newItem); - } - protected override void TriggerOnRefreshStart() { } @@ -421,10 +416,15 @@ namespace MediaBrowser.Controller.Entities { BaseItem currentChild; - if (currentChildren.TryGetValue(child.Id, out currentChild) && IsValidFromResolver(currentChild, child)) + if (currentChildren.TryGetValue(child.Id, out currentChild) && currentChild.IsValidFromResolver(child)) { validChildren.Add(currentChild); + if (currentChild.UpdateFromResolvedItem(child) > ItemUpdateType.None) + { + currentChild.UpdateToRepository(ItemUpdateType.MetadataImport, cancellationToken); + } + continue; } @@ -542,7 +542,6 @@ namespace MediaBrowser.Controller.Entities if (validChildrenNeedGeneration) { validChildren = Children.ToList(); - validChildrenNeedGeneration = false; } await RefreshMetadataRecursive(validChildren, refreshOptions, recursive, innerProgress, cancellationToken); diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs index a99058925..bead0ef95 100644 --- a/MediaBrowser.Controller/Entities/Game.cs +++ b/MediaBrowser.Controller/Entities/Game.cs @@ -29,15 +29,15 @@ namespace MediaBrowser.Controller.Entities } [IgnoreDataMember] - public override bool EnableRefreshOnDateModifiedChange + public override bool SupportsThemeMedia { get { return true; } } [IgnoreDataMember] - public override bool SupportsThemeMedia + public override bool SupportsPeople { - get { return true; } + get { return false; } } /// <summary> diff --git a/MediaBrowser.Controller/Entities/IHasMetadata.cs b/MediaBrowser.Controller/Entities/IHasMetadata.cs index 4146686b2..b7d31b4d6 100644 --- a/MediaBrowser.Controller/Entities/IHasMetadata.cs +++ b/MediaBrowser.Controller/Entities/IHasMetadata.cs @@ -151,11 +151,7 @@ namespace MediaBrowser.Controller.Entities /// <summary> /// Swaps the images. /// </summary> - /// <param name="type">The type.</param> - /// <param name="index1">The index1.</param> - /// <param name="index2">The index2.</param> - /// <returns>Task.</returns> - Task SwapImages(ImageType type, int index1, int index2); + void SwapImages(ImageType type, int index1, int index2); /// <summary> /// Gets or sets the primary image path. @@ -249,10 +245,7 @@ namespace MediaBrowser.Controller.Entities /// <summary> /// Updates to repository. /// </summary> - /// <param name="updateReason">The update reason.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - Task UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken); + void UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken); /// <summary> /// Sets the image. diff --git a/MediaBrowser.Controller/Entities/ItemImageInfo.cs b/MediaBrowser.Controller/Entities/ItemImageInfo.cs index 6b2d2392d..bd0011c4b 100644 --- a/MediaBrowser.Controller/Entities/ItemImageInfo.cs +++ b/MediaBrowser.Controller/Entities/ItemImageInfo.cs @@ -24,6 +24,9 @@ namespace MediaBrowser.Controller.Entities /// <value>The date modified.</value> public DateTime DateModified { get; set; } + public int Width { get; set; } + public int Height { get; set; } + [IgnoreDataMember] public bool IsLocalFile { diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs index bd8d9024d..268860ff0 100644 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs @@ -45,6 +45,12 @@ namespace MediaBrowser.Controller.Entities.Movies } } + [IgnoreDataMember] + public override bool SupportsPeople + { + get { return true; } + } + public Guid[] LocalTrailerIds { get; set; } public Guid[] RemoteTrailerIds { get; set; } @@ -126,7 +132,7 @@ namespace MediaBrowser.Controller.Entities.Movies } } - public override bool IsAuthorizedToDelete(User user) + public override bool IsAuthorizedToDelete(User user, List<Folder> allCollectionFolders) { return true; } diff --git a/MediaBrowser.Controller/Entities/PhotoAlbum.cs b/MediaBrowser.Controller/Entities/PhotoAlbum.cs index 52d743e36..af9d8c801 100644 --- a/MediaBrowser.Controller/Entities/PhotoAlbum.cs +++ b/MediaBrowser.Controller/Entities/PhotoAlbum.cs @@ -30,10 +30,5 @@ namespace MediaBrowser.Controller.Entities return false; } } - - public override double? GetDefaultPrimaryImageAspectRatio() - { - return 1; - } } } diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs index c30e0ef8e..3f52dfc93 100644 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ b/MediaBrowser.Controller/Entities/TV/Episode.cs @@ -79,6 +79,12 @@ namespace MediaBrowser.Controller.Entities.TV }
[IgnoreDataMember]
+ public override bool SupportsPeople
+ {
+ get { return true; }
+ }
+
+ [IgnoreDataMember]
public int? AiredSeasonNumber
{
get
diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs index bf6dc5678..00bb75fa7 100644 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ b/MediaBrowser.Controller/Entities/TV/Season.cs @@ -41,6 +41,12 @@ namespace MediaBrowser.Controller.Entities.TV } [IgnoreDataMember] + public override bool SupportsPeople + { + get { return true; } + } + + [IgnoreDataMember] public override bool SupportsInheritedParentImages { get { return true; } diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs index 5931c32e1..1d09783d1 100644 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ b/MediaBrowser.Controller/Entities/TV/Series.cs @@ -64,6 +64,12 @@ namespace MediaBrowser.Controller.Entities.TV } } + [IgnoreDataMember] + public override bool SupportsPeople + { + get { return true; } + } + public Guid[] LocalTrailerIds { get; set; } public Guid[] RemoteTrailerIds { get; set; } diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs index 36bbf6886..821327b7f 100644 --- a/MediaBrowser.Controller/Entities/User.cs +++ b/MediaBrowser.Controller/Entities/User.cs @@ -235,10 +235,9 @@ namespace MediaBrowser.Controller.Entities }, CancellationToken.None); } - public override Task UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken) + public override void UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken) { UserManager.UpdateUser(this); - return Task.FromResult(true); } /// <summary> diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs index 43adc4af6..97b96127a 100644 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs @@ -78,26 +78,26 @@ namespace MediaBrowser.Controller.Entities case SpecialFolder.LiveTvChannels: { - var result = await _liveTvManager.GetInternalChannels(new LiveTvChannelQuery + var result = _liveTvManager.GetInternalChannels(new LiveTvChannelQuery { UserId = query.User.Id.ToString("N"), Limit = query.Limit, StartIndex = query.StartIndex - }, new DtoOptions(), CancellationToken.None).ConfigureAwait(false); + }, new DtoOptions(), CancellationToken.None); return GetResult(result); } case SpecialFolder.LiveTvNowPlaying: { - var result = await _liveTvManager.GetRecommendedProgramsInternal(new RecommendedProgramQuery + var result = _liveTvManager.GetRecommendedProgramsInternal(new RecommendedProgramQuery { UserId = query.User.Id.ToString("N"), Limit = query.Limit, IsAiring = true - }, new Dto.DtoOptions(), CancellationToken.None).ConfigureAwait(false); + }, new Dto.DtoOptions(), CancellationToken.None); return GetResult(result); } @@ -142,22 +142,22 @@ namespace MediaBrowser.Controller.Entities return GetResult(user.RootFolder.GetChildren(user, true), queryParent, query); case CollectionType.Playlists: - return GetPlaylistsView(queryParent, user, query); + return GetPlaylistsView(queryParent, user, query); case CollectionType.BoxSets: return GetBoxsetView(queryParent, user, query); case CollectionType.TvShows: - return await GetTvView(queryParent, user, query).ConfigureAwait(false); + return GetTvView(queryParent, user, query); case CollectionType.Movies: - return await GetMovieFolders(queryParent, user, query).ConfigureAwait(false); + return GetMovieFolders(queryParent, user, query); case SpecialFolder.TvShowSeries: return GetTvSeries(queryParent, user, query); case SpecialFolder.TvGenres: - return await GetTvGenres(queryParent, user, query).ConfigureAwait(false); + return GetTvGenres(queryParent, user, query); case SpecialFolder.TvGenre: return GetTvGenreItems(queryParent, displayParent, user, query); @@ -178,10 +178,10 @@ namespace MediaBrowser.Controller.Entities return GetMovieLatest(queryParent, user, query); case SpecialFolder.MovieGenres: - return await GetMovieGenres(queryParent, user, query).ConfigureAwait(false); + return GetMovieGenres(queryParent, user, query); case SpecialFolder.MovieGenre: - return GetMovieGenreItems(queryParent, displayParent, user, query); + return GetMovieGenreItems(queryParent, displayParent, user, query); case SpecialFolder.MovieResume: return GetMovieResume(queryParent, user, query); @@ -199,7 +199,7 @@ namespace MediaBrowser.Controller.Entities return GetFavoriteSeries(queryParent, user, query); case CollectionType.Music: - return await GetMusicFolders(queryParent, user, query).ConfigureAwait(false); + return GetMusicFolders(queryParent, user, query); case SpecialFolder.MusicGenres: return GetMusicGenres(queryParent, user, query); @@ -223,7 +223,7 @@ namespace MediaBrowser.Controller.Entities return GetMusicSongs(queryParent, user, query); case SpecialFolder.MusicFavorites: - return await GetMusicFavorites(queryParent, user, query).ConfigureAwait(false); + return GetMusicFavorites(queryParent, user, query); case SpecialFolder.MusicFavoriteAlbums: return GetFavoriteAlbums(queryParent, user, query); @@ -245,7 +245,7 @@ namespace MediaBrowser.Controller.Entities } } - private async Task<QueryResult<BaseItem>> GetMusicFolders(Folder parent, User user, InternalItemsQuery query) + private QueryResult<BaseItem> GetMusicFolders(Folder parent, User user, InternalItemsQuery query) { if (query.Recursive) { @@ -262,25 +262,25 @@ namespace MediaBrowser.Controller.Entities var list = new List<BaseItem>(); - list.Add(await GetUserView(SpecialFolder.MusicLatest, "0", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.MusicPlaylists, "1", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.MusicAlbums, "2", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.MusicAlbumArtists, "3", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.MusicArtists, "4", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.MusicSongs, "5", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.MusicGenres, "6", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.MusicFavorites, "7", parent).ConfigureAwait(false)); + list.Add(GetUserView(SpecialFolder.MusicLatest, "Latest", "0", parent)); + list.Add(GetUserView(SpecialFolder.MusicPlaylists, "Playlists", "1", parent)); + list.Add(GetUserView(SpecialFolder.MusicAlbums, "Albums", "2", parent)); + list.Add(GetUserView(SpecialFolder.MusicAlbumArtists, "HeaderAlbumArtists", "3", parent)); + list.Add(GetUserView(SpecialFolder.MusicArtists, "Artists", "4", parent)); + list.Add(GetUserView(SpecialFolder.MusicSongs, "Songs", "5", parent)); + list.Add(GetUserView(SpecialFolder.MusicGenres, "Genres", "6", parent)); + list.Add(GetUserView(SpecialFolder.MusicFavorites, "Favorites", "7", parent)); return GetResult(list, parent, query); } - private async Task<QueryResult<BaseItem>> GetMusicFavorites(Folder parent, User user, InternalItemsQuery query) + private QueryResult<BaseItem> GetMusicFavorites(Folder parent, User user, InternalItemsQuery query) { var list = new List<BaseItem>(); - list.Add(await GetUserView(SpecialFolder.MusicFavoriteAlbums, "0", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.MusicFavoriteArtists, "1", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.MusicFavoriteSongs, "2", parent).ConfigureAwait(false)); + list.Add(GetUserView(SpecialFolder.MusicFavoriteAlbums, "HeaderFavoriteAlbums", "0", parent)); + list.Add(GetUserView(SpecialFolder.MusicFavoriteArtists, "HeaderFavoriteArtists", "1", parent)); + list.Add(GetUserView(SpecialFolder.MusicFavoriteSongs, "HeaderFavoriteSongs", "2", parent)); return GetResult(list, parent, query); } @@ -426,7 +426,7 @@ namespace MediaBrowser.Controller.Entities return 50; } - private async Task<QueryResult<BaseItem>> GetMovieFolders(Folder parent, User user, InternalItemsQuery query) + private QueryResult<BaseItem> GetMovieFolders(Folder parent, User user, InternalItemsQuery query) { if (query.Recursive) { @@ -443,12 +443,12 @@ namespace MediaBrowser.Controller.Entities var list = new List<BaseItem>(); - list.Add(await GetUserView(SpecialFolder.MovieResume, "0", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.MovieLatest, "1", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.MovieMovies, "2", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.MovieCollections, "3", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.MovieFavorites, "4", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.MovieGenres, "5", parent).ConfigureAwait(false)); + list.Add(GetUserView(SpecialFolder.MovieResume, "HeaderContinueWatching", "0", parent)); + list.Add(GetUserView(SpecialFolder.MovieLatest, "Latest", "1", parent)); + list.Add(GetUserView(SpecialFolder.MovieMovies, "Movies", "2", parent)); + list.Add(GetUserView(SpecialFolder.MovieCollections, "Collections", "3", parent)); + list.Add(GetUserView(SpecialFolder.MovieFavorites, "Favorites", "4", parent)); + list.Add(GetUserView(SpecialFolder.MovieGenres, "Genres", "5", parent)); return GetResult(list, parent, query); } @@ -538,9 +538,9 @@ namespace MediaBrowser.Controller.Entities }; } - private async Task<QueryResult<BaseItem>> GetMovieGenres(Folder parent, User user, InternalItemsQuery query) + private QueryResult<BaseItem> GetMovieGenres(Folder parent, User user, InternalItemsQuery query) { - var tasks = parent.QueryRecursive(new InternalItemsQuery(user) + var genres = parent.QueryRecursive(new InternalItemsQuery(user) { IncludeItemTypes = new[] { typeof(Movie).Name }, Recursive = true, @@ -564,9 +564,7 @@ namespace MediaBrowser.Controller.Entities }) .Where(i => i != null) - .Select(i => GetUserView(i.Name, SpecialFolder.MovieGenre, i.SortName, parent)); - - var genres = await Task.WhenAll(tasks).ConfigureAwait(false); + .Select(i => GetUserViewWithName(i.Name, SpecialFolder.MovieGenre, i.SortName, parent)); return GetResult(genres, parent, query); } @@ -598,7 +596,7 @@ namespace MediaBrowser.Controller.Entities return _libraryManager.GetItemsResult(query); } - private async Task<QueryResult<BaseItem>> GetTvView(Folder parent, User user, InternalItemsQuery query) + private QueryResult<BaseItem> GetTvView(Folder parent, User user, InternalItemsQuery query) { if (query.Recursive) { @@ -615,13 +613,13 @@ namespace MediaBrowser.Controller.Entities var list = new List<BaseItem>(); - list.Add(await GetUserView(SpecialFolder.TvResume, "0", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.TvNextUp, "1", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.TvLatest, "2", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.TvShowSeries, "3", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.TvFavoriteSeries, "4", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.TvFavoriteEpisodes, "5", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.TvGenres, "6", parent).ConfigureAwait(false)); + list.Add(GetUserView(SpecialFolder.TvResume, "HeaderContinueWatching", "0", parent)); + list.Add(GetUserView(SpecialFolder.TvNextUp, "HeaderNextUp", "1", parent)); + list.Add(GetUserView(SpecialFolder.TvLatest, "Latest", "2", parent)); + list.Add(GetUserView(SpecialFolder.TvShowSeries, "Shows", "3", parent)); + list.Add(GetUserView(SpecialFolder.TvFavoriteSeries, "HeaderFavoriteShows", "4", parent)); + list.Add(GetUserView(SpecialFolder.TvFavoriteEpisodes, "HeaderFavoriteEpisodes", "5", parent)); + list.Add(GetUserView(SpecialFolder.TvGenres, "Genres", "6", parent)); return GetResult(list, parent, query); } @@ -679,9 +677,9 @@ namespace MediaBrowser.Controller.Entities return _libraryManager.GetItemsResult(query); } - private async Task<QueryResult<BaseItem>> GetTvGenres(Folder parent, User user, InternalItemsQuery query) + private QueryResult<BaseItem> GetTvGenres(Folder parent, User user, InternalItemsQuery query) { - var tasks = parent.QueryRecursive(new InternalItemsQuery(user) + var genres = parent.QueryRecursive(new InternalItemsQuery(user) { IncludeItemTypes = new[] { typeof(Series).Name }, Recursive = true, @@ -705,9 +703,7 @@ namespace MediaBrowser.Controller.Entities }) .Where(i => i != null) - .Select(i => GetUserView(i.Name, SpecialFolder.TvGenre, i.SortName, parent)); - - var genres = await Task.WhenAll(tasks).ConfigureAwait(false); + .Select(i => GetUserViewWithName(i.Name, SpecialFolder.TvGenre, i.SortName, parent)); return GetResult(genres, parent, query); } @@ -1740,20 +1736,20 @@ namespace MediaBrowser.Controller.Entities var list = new List<BaseItem>(); //list.Add(await GetUserSubView(SpecialFolder.LiveTvNowPlaying, user, "0", parent).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.LiveTvChannels, string.Empty, user.RootFolder).ConfigureAwait(false)); - list.Add(await GetUserView(SpecialFolder.LiveTvRecordingGroups, string.Empty, user.RootFolder).ConfigureAwait(false)); + list.Add(GetUserView(SpecialFolder.LiveTvChannels, "Channels", string.Empty, user.RootFolder)); + list.Add(GetUserView(SpecialFolder.LiveTvRecordingGroups, "HeaderRecordingGroups", string.Empty, user.RootFolder)); return GetResult(list, queryParent, query); } - private Task<UserView> GetUserView(string name, string type, string sortName, BaseItem parent) + private UserView GetUserViewWithName(string name, string type, string sortName, BaseItem parent) { return _userViewManager.GetUserSubView(name, parent.Id.ToString("N"), type, sortName, CancellationToken.None); } - private Task<UserView> GetUserView(string type, string sortName, BaseItem parent) + private UserView GetUserView(string type, string localizationKey, string sortName, BaseItem parent) { - return _userViewManager.GetUserSubView(parent.Id.ToString("N"), type, sortName, CancellationToken.None); + return _userViewManager.GetUserSubView(parent.Id.ToString("N"), type, localizationKey, sortName, CancellationToken.None); } public static IEnumerable<BaseItem> FilterForAdjacency(List<BaseItem> list, string adjacentToId) diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 8693d867c..52f1dd051 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/MediaBrowser.Controller/Entities/Video.cs @@ -45,6 +45,12 @@ namespace MediaBrowser.Controller.Entities } [IgnoreDataMember] + public override bool SupportsPeople + { + get { return true; } + } + + [IgnoreDataMember] public override bool SupportsInheritedParentImages { get @@ -78,14 +84,6 @@ namespace MediaBrowser.Controller.Entities } } - public override double? GetDefaultPrimaryImageAspectRatio() - { - double value = 16; - value /= 9; - - return value; - } - public override string CreatePresentationUniqueKey() { if (!string.IsNullOrWhiteSpace(PrimaryVersionId)) @@ -406,30 +404,31 @@ namespace MediaBrowser.Controller.Entities } } - internal override bool IsValidFromResolver(BaseItem newItem) + internal override ItemUpdateType UpdateFromResolvedItem(BaseItem newItem) { - var current = this; + var updateType = base.UpdateFromResolvedItem(newItem); - var newAsVideo = newItem as Video; - - if (newAsVideo != null) + var newVideo = newItem as Video; + if (newVideo != null) { - if (!current.AdditionalParts.SequenceEqual(newAsVideo.AdditionalParts, StringComparer.OrdinalIgnoreCase)) + if (!AdditionalParts.SequenceEqual(newVideo.AdditionalParts, StringComparer.Ordinal)) { - return false; + AdditionalParts = newVideo.AdditionalParts; + updateType |= ItemUpdateType.MetadataImport; } - if (!current.LocalAlternateVersions.SequenceEqual(newAsVideo.LocalAlternateVersions, StringComparer.OrdinalIgnoreCase)) + if (!LocalAlternateVersions.SequenceEqual(newVideo.LocalAlternateVersions, StringComparer.Ordinal)) { - return false; + LocalAlternateVersions = newVideo.LocalAlternateVersions; + updateType |= ItemUpdateType.MetadataImport; } - - if (newAsVideo.VideoType != VideoType) + if (VideoType != newVideo.VideoType) { - return false; + VideoType = newVideo.VideoType; + updateType |= ItemUpdateType.MetadataImport; } } - return base.IsValidFromResolver(newItem); + return updateType; } public static string[] QueryPlayableStreamFiles(string rootPath, VideoType videoType) @@ -521,9 +520,9 @@ namespace MediaBrowser.Controller.Entities } } - public override async Task UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken) + public override void UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken) { - await base.UpdateToRepository(updateReason, cancellationToken).ConfigureAwait(false); + base.UpdateToRepository(updateReason, cancellationToken); var localAlternates = GetLocalAlternateVersionIds() .Select(i => LibraryManager.GetItemById(i)) @@ -540,7 +539,7 @@ namespace MediaBrowser.Controller.Entities item.Genres = Genres; item.ProviderIds = ProviderIds; - await item.UpdateToRepository(ItemUpdateType.MetadataDownload, cancellationToken).ConfigureAwait(false); + item.UpdateToRepository(ItemUpdateType.MetadataDownload, cancellationToken); } } diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 3001e3366..37e0d5661 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -128,6 +128,8 @@ namespace MediaBrowser.Controller.Library /// </summary> void QueueLibraryScan(); + void UpdateImages(BaseItem item); + /// <summary> /// Gets the default view. /// </summary> @@ -207,11 +209,7 @@ namespace MediaBrowser.Controller.Library /// <summary> /// Updates the item. /// </summary> - /// <param name="item">The item.</param> - /// <param name="updateReason">The update reason.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - Task UpdateItem(BaseItem item, ItemUpdateType updateReason, CancellationToken cancellationToken); + void UpdateItem(BaseItem item, ItemUpdateType updateReason, CancellationToken cancellationToken); /// <summary> /// Retrieves the item. @@ -330,8 +328,7 @@ namespace MediaBrowser.Controller.Library /// <param name="viewType">Type of the view.</param> /// <param name="sortName">Name of the sort.</param> /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task<UserView>.</returns> - Task<UserView> GetNamedView(string name, + UserView GetNamedView(string name, string viewType, string sortName, CancellationToken cancellationToken); @@ -345,8 +342,7 @@ namespace MediaBrowser.Controller.Library /// <param name="sortName">Name of the sort.</param> /// <param name="uniqueId">The unique identifier.</param> /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task<UserView>.</returns> - Task<UserView> GetNamedView(string name, + UserView GetNamedView(string name, string parentId, string viewType, string sortName, diff --git a/MediaBrowser.Controller/Library/IUserViewManager.cs b/MediaBrowser.Controller/Library/IUserViewManager.cs index 76182c641..baecdd748 100644 --- a/MediaBrowser.Controller/Library/IUserViewManager.cs +++ b/MediaBrowser.Controller/Library/IUserViewManager.cs @@ -13,9 +13,9 @@ namespace MediaBrowser.Controller.Library { Task<Folder[]> GetUserViews(UserViewQuery query, CancellationToken cancellationToken); - Task<UserView> GetUserSubView(string name, string parentId, string type, string sortName, CancellationToken cancellationToken); + UserView GetUserSubViewWithName(string name, string parentId, string type, string sortName, CancellationToken cancellationToken); - Task<UserView> GetUserSubView(string category, string type, string sortName, CancellationToken cancellationToken); + UserView GetUserSubView(string category, string type, string localizationKey, string sortName, CancellationToken cancellationToken); List<Tuple<BaseItem, List<BaseItem>>> GetLatestItems(LatestItemsQuery request, DtoOptions options); } diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs index be85e115c..4934cc1ca 100644 --- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs +++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs @@ -76,16 +76,6 @@ namespace MediaBrowser.Controller.LiveTv void AddParts(IEnumerable<ILiveTvService> services, IEnumerable<ITunerHost> tunerHosts, IEnumerable<IListingsProvider> listingProviders); /// <summary> - /// Gets the recording. - /// </summary> - /// <param name="id">The identifier.</param> - /// <param name="options">The options.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="user">The user.</param> - /// <returns>Task{RecordingInfoDto}.</returns> - Task<BaseItemDto> GetRecording(string id, DtoOptions options, CancellationToken cancellationToken, User user = null); - - /// <summary> /// Gets the timer. /// </summary> /// <param name="id">The identifier.</param> @@ -236,14 +226,12 @@ namespace MediaBrowser.Controller.LiveTv /// <param name="query">The query.</param> /// <param name="options">The options.</param> /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task{QueryResult{ProgramInfoDto}}.</returns> - Task<QueryResult<BaseItemDto>> GetRecommendedPrograms(RecommendedProgramQuery query, DtoOptions options, CancellationToken cancellationToken); + QueryResult<BaseItemDto> GetRecommendedPrograms(RecommendedProgramQuery query, DtoOptions options, CancellationToken cancellationToken); /// <summary> /// Gets the recommended programs internal. /// </summary> - /// <returns>Task<QueryResult<LiveTvProgram>>.</returns> - Task<QueryResult<BaseItem>> GetRecommendedProgramsInternal(RecommendedProgramQuery query, DtoOptions options, CancellationToken cancellationToken); + QueryResult<BaseItem> GetRecommendedProgramsInternal(RecommendedProgramQuery query, DtoOptions options, CancellationToken cancellationToken); /// <summary> /// Gets the live tv information. @@ -264,8 +252,7 @@ namespace MediaBrowser.Controller.LiveTv /// Gets the live tv folder. /// </summary> /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>BaseItemDto.</returns> - Task<Folder> GetInternalLiveTvFolder(CancellationToken cancellationToken); + Folder GetInternalLiveTvFolder(CancellationToken cancellationToken); /// <summary> /// Gets the live tv folder. @@ -273,7 +260,7 @@ namespace MediaBrowser.Controller.LiveTv /// <param name="userId">The user identifier.</param> /// <param name="cancellationToken">The cancellation token.</param> /// <returns>BaseItemDto.</returns> - Task<BaseItemDto> GetLiveTvFolder(string userId, CancellationToken cancellationToken); + BaseItemDto GetLiveTvFolder(string userId, CancellationToken cancellationToken); /// <summary> /// Gets the enabled users. @@ -284,7 +271,7 @@ namespace MediaBrowser.Controller.LiveTv /// <summary> /// Gets the internal channels. /// </summary> - Task<QueryResult<BaseItem>> GetInternalChannels(LiveTvChannelQuery query, DtoOptions dtoOptions, CancellationToken cancellationToken); + QueryResult<BaseItem> GetInternalChannels(LiveTvChannelQuery query, DtoOptions dtoOptions, CancellationToken cancellationToken); /// <summary> /// Gets the internal recordings. @@ -362,13 +349,6 @@ namespace MediaBrowser.Controller.LiveTv /// <param name="user">The user.</param> void AddChannelInfo(List<Tuple<BaseItemDto, LiveTvChannel>> items, DtoOptions options, User user); - /// <summary> - /// Called when [recording file deleted]. - /// </summary> - /// <param name="recording">The recording.</param> - /// <returns>Task.</returns> - Task OnRecordingFileDeleted(BaseItem recording); - Task<List<ChannelInfo>> GetChannelsForListingsProvider(string id, CancellationToken cancellationToken); Task<List<ChannelInfo>> GetChannelsFromListingsProviderData(string id, CancellationToken cancellationToken); diff --git a/MediaBrowser.Controller/LiveTv/ITunerHost.cs b/MediaBrowser.Controller/LiveTv/ITunerHost.cs index 2019259c5..523eec24a 100644 --- a/MediaBrowser.Controller/LiveTv/ITunerHost.cs +++ b/MediaBrowser.Controller/LiveTv/ITunerHost.cs @@ -59,8 +59,8 @@ namespace MediaBrowser.Controller.LiveTv public interface ILiveStream { - Task Open(CancellationToken cancellationToken); - Task Close(); + Task Open(CancellationToken openCancellationToken); + void Close(); int ConsumerCount { get; } string OriginalStreamId { get; set; } bool EnableStreamSharing { get; set; } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs index 8fa96076b..bd84541f8 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs @@ -132,7 +132,7 @@ namespace MediaBrowser.Controller.LiveTv return true; } - public override bool IsAuthorizedToDelete(User user) + public override bool IsAuthorizedToDelete(User user, List<Folder> allCollectionFolders) { return user.Policy.EnableLiveTvManagement; } @@ -161,10 +161,5 @@ namespace MediaBrowser.Controller.LiveTv { return LiveTvManager.DeleteRecording(this); } - - public override Task OnFileDeleted() - { - return LiveTvManager.OnRecordingFileDeleted(this); - } } } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs index 4a93d0399..16010b7f5 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs @@ -136,7 +136,8 @@ namespace MediaBrowser.Controller.LiveTv Name = Name, Path = Path, RunTimeTicks = RunTimeTicks, - Type = MediaSourceType.Placeholder + Type = MediaSourceType.Placeholder, + IsInfiniteStream = RunTimeTicks == null }; list.Add(info); diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs index 1c1637330..9dff18690 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs @@ -50,21 +50,40 @@ namespace MediaBrowser.Controller.LiveTv public static double? GetDefaultPrimaryImageAspectRatio(IHasProgramAttributes item) { var serviceName = item.ServiceName; - if (!item.IsMovie - && !string.Equals(serviceName, EmbyServiceName, StringComparison.OrdinalIgnoreCase) - && !string.Equals(serviceName, "Next Pvr", StringComparison.OrdinalIgnoreCase)) + + if (item.IsMovie) { - double value = 16; - value /= 9; + if (string.Equals(serviceName, EmbyServiceName, StringComparison.OrdinalIgnoreCase) || string.Equals(serviceName, "Next Pvr", StringComparison.OrdinalIgnoreCase)) + { + double value = 2; + value /= 3; + + return value; + } + else + { + double value = 16; + value /= 9; - return value; + return value; + } } else { - double value = 2; - value /= 3; + if (string.Equals(serviceName, EmbyServiceName, StringComparison.OrdinalIgnoreCase) || string.Equals(serviceName, "Next Pvr", StringComparison.OrdinalIgnoreCase)) + { + double value = 2; + value /= 3; - return value; + return value; + } + else + { + double value = 16; + value /= 9; + + return value; + } } } diff --git a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs index c5fe7b1b3..37c1faac6 100644 --- a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs +++ b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs @@ -131,7 +131,7 @@ namespace MediaBrowser.Controller.LiveTv return true; } - public override bool IsAuthorizedToDelete(User user) + public override bool IsAuthorizedToDelete(User user, List<Folder> allCollectionFolders) { return user.Policy.EnableLiveTvManagement; } @@ -160,10 +160,5 @@ namespace MediaBrowser.Controller.LiveTv { return LiveTvManager.DeleteRecording(this); } - - public override Task OnFileDeleted() - { - return LiveTvManager.OnRecordingFileDeleted(this); - } } } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index b33993859..dafca0598 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -176,6 +176,7 @@ <Compile Include="MediaEncoding\MediaStreamSelector.cs" /> <Compile Include="Net\AuthenticatedAttribute.cs" /> <Compile Include="Net\AuthorizationInfo.cs" /> + <Compile Include="Net\BasePeriodicWebSocketListener.cs" /> <Compile Include="Net\IAuthorizationContext.cs" /> <Compile Include="Net\IAuthService.cs" /> <Compile Include="Net\IHasResultFactory.cs" /> @@ -219,7 +220,6 @@ <Compile Include="Providers\IExternalId.cs" /> <Compile Include="Providers\IExtrasProvider.cs" /> <Compile Include="Providers\IForcedProvider.cs" /> - <Compile Include="Providers\IHasChangeMonitor.cs" /> <Compile Include="Entities\IHasMetadata.cs" /> <Compile Include="Providers\IHasItemChangeMonitor.cs" /> <Compile Include="Providers\IHasLookupInfo.cs" /> diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 8b612f809..bddafe9a6 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -794,11 +794,6 @@ namespace MediaBrowser.Controller.MediaEncoding return false; } - if (state.EnableMpDecimate) - { - return false; - } - if (videoStream.IsInterlaced) { if (state.DeInterlace(videoStream.Codec, false)) @@ -1515,11 +1510,6 @@ namespace MediaBrowser.Controller.MediaEncoding } } - if (state.EnableMpDecimate) - { - filters.Add("mpdecimate,setpts=N/FRAME_RATE/TB"); - } - if (filters.Count > 0) { output += string.Format(" -vf \"{0}\"", string.Join(",", filters.ToArray())); @@ -1638,7 +1628,7 @@ namespace MediaBrowser.Controller.MediaEncoding if (state.InputProtocol == MediaProtocol.Rtsp) { - inputModifier += " -rtsp_transport tcp"; + inputModifier += " -rtsp_transport tcp -rtsp_transport udp -rtsp_flags prefer_tcp"; } if (!string.IsNullOrEmpty(state.InputAudioSync)) @@ -1960,6 +1950,12 @@ namespace MediaBrowser.Controller.MediaEncoding return "-c:v h264_mmal"; } break; + case "mpeg2video": + if (_mediaEncoder.SupportsDecoder("mpeg2_mmal") && encodingOptions.HardwareDecodingCodecs.Contains("mpeg2video", StringComparer.OrdinalIgnoreCase)) + { + return "-c:v mpeg2_mmal"; + } + break; } } } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs index 506fce3ca..ad131064c 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobInfo.cs @@ -127,11 +127,6 @@ namespace MediaBrowser.Controller.MediaEncoding } } - public bool EnableMpDecimate - { - get { return MediaSource.EnableMpDecimate; } - } - public string AlbumCoverPath { get; set; } public string InputAudioSync { get; set; } diff --git a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs new file mode 100644 index 000000000..6be94e7e6 --- /dev/null +++ b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs @@ -0,0 +1,326 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Net; +using MediaBrowser.Model.Threading; + +namespace MediaBrowser.Controller.Net +{ + /// <summary> + /// Starts sending data over a web socket periodically when a message is received, and then stops when a corresponding stop message is received + /// </summary> + /// <typeparam name="TReturnDataType">The type of the T return data type.</typeparam> + /// <typeparam name="TStateType">The type of the T state type.</typeparam> + public abstract class BasePeriodicWebSocketListener<TReturnDataType, TStateType> : IWebSocketListener, IDisposable + where TStateType : WebSocketListenerState, new() + where TReturnDataType : class + { + /// <summary> + /// The _active connections + /// </summary> + protected readonly List<Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType>> ActiveConnections = + new List<Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType>>(); + + /// <summary> + /// Gets the name. + /// </summary> + /// <value>The name.</value> + protected abstract string Name { get; } + + /// <summary> + /// Gets the data to send. + /// </summary> + /// <param name="state">The state.</param> + /// <returns>Task{`1}.</returns> + protected abstract Task<TReturnDataType> GetDataToSend(TStateType state); + + /// <summary> + /// The logger + /// </summary> + protected ILogger Logger; + + protected ITimerFactory TimerFactory { get; private set; } + + protected BasePeriodicWebSocketListener(ILogger logger, ITimerFactory timerFactory) + { + if (logger == null) + { + throw new ArgumentNullException("logger"); + } + + Logger = logger; + TimerFactory = timerFactory; + } + + /// <summary> + /// The null task result + /// </summary> + protected Task NullTaskResult = Task.FromResult(true); + + /// <summary> + /// Processes the message. + /// </summary> + /// <param name="message">The message.</param> + /// <returns>Task.</returns> + public Task ProcessMessage(WebSocketMessageInfo message) + { + if (message == null) + { + throw new ArgumentNullException("message"); + } + + if (string.Equals(message.MessageType, Name + "Start", StringComparison.OrdinalIgnoreCase)) + { + Start(message); + } + + if (string.Equals(message.MessageType, Name + "Stop", StringComparison.OrdinalIgnoreCase)) + { + Stop(message); + } + + return NullTaskResult; + } + + protected readonly CultureInfo UsCulture = new CultureInfo("en-US"); + + protected virtual bool SendOnTimer + { + get + { + return false; + } + } + + protected virtual void ParseMessageParams(string[] values) + { + + } + + /// <summary> + /// Starts sending messages over a web socket + /// </summary> + /// <param name="message">The message.</param> + private void Start(WebSocketMessageInfo message) + { + var vals = message.Data.Split(','); + + var dueTimeMs = long.Parse(vals[0], UsCulture); + var periodMs = long.Parse(vals[1], UsCulture); + + if (vals.Length > 2) + { + ParseMessageParams(vals.Skip(2).ToArray()); + } + + var cancellationTokenSource = new CancellationTokenSource(); + + Logger.Debug("{1} Begin transmitting over websocket to {0}", message.Connection.RemoteEndPoint, GetType().Name); + + var timer = SendOnTimer ? + TimerFactory.Create(TimerCallback, message.Connection, Timeout.Infinite, Timeout.Infinite) : + null; + + var state = new TStateType + { + IntervalMs = periodMs, + InitialDelayMs = dueTimeMs + }; + + lock (ActiveConnections) + { + ActiveConnections.Add(new Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType>(message.Connection, cancellationTokenSource, timer, state)); + } + + if (timer != null) + { + timer.Change(TimeSpan.FromMilliseconds(dueTimeMs), TimeSpan.FromMilliseconds(periodMs)); + } + } + + /// <summary> + /// Timers the callback. + /// </summary> + /// <param name="state">The state.</param> + private void TimerCallback(object state) + { + var connection = (IWebSocketConnection)state; + + Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType> tuple; + + lock (ActiveConnections) + { + tuple = ActiveConnections.FirstOrDefault(c => c.Item1 == connection); + } + + if (tuple == null) + { + return; + } + + if (connection.State != WebSocketState.Open || tuple.Item2.IsCancellationRequested) + { + DisposeConnection(tuple); + return; + } + + SendData(tuple); + } + + protected void SendData(bool force) + { + List<Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType>> tuples; + + lock (ActiveConnections) + { + tuples = ActiveConnections + .Where(c => + { + if (c.Item1.State == WebSocketState.Open && !c.Item2.IsCancellationRequested) + { + var state = c.Item4; + + if (force || (DateTime.UtcNow - state.DateLastSendUtc).TotalMilliseconds >= state.IntervalMs) + { + return true; + } + } + + return false; + }) + .ToList(); + } + + foreach (var tuple in tuples) + { + SendData(tuple); + } + } + + private async void SendData(Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType> tuple) + { + var connection = tuple.Item1; + + try + { + var state = tuple.Item4; + + var data = await GetDataToSend(state).ConfigureAwait(false); + + if (data != null) + { + await connection.SendAsync(new WebSocketMessage<TReturnDataType> + { + MessageType = Name, + Data = data + + }, tuple.Item2.Token).ConfigureAwait(false); + + state.DateLastSendUtc = DateTime.UtcNow; + } + } + catch (OperationCanceledException) + { + if (tuple.Item2.IsCancellationRequested) + { + DisposeConnection(tuple); + } + } + catch (Exception ex) + { + Logger.ErrorException("Error sending web socket message {0}", ex, Name); + DisposeConnection(tuple); + } + } + + /// <summary> + /// Stops sending messages over a web socket + /// </summary> + /// <param name="message">The message.</param> + private void Stop(WebSocketMessageInfo message) + { + lock (ActiveConnections) + { + var connection = ActiveConnections.FirstOrDefault(c => c.Item1 == message.Connection); + + if (connection != null) + { + DisposeConnection(connection); + } + } + } + + /// <summary> + /// Disposes the connection. + /// </summary> + /// <param name="connection">The connection.</param> + private void DisposeConnection(Tuple<IWebSocketConnection, CancellationTokenSource, ITimer, TStateType> connection) + { + Logger.Debug("{1} stop transmitting over websocket to {0}", connection.Item1.RemoteEndPoint, GetType().Name); + + var timer = connection.Item3; + + if (timer != null) + { + try + { + timer.Dispose(); + } + catch (ObjectDisposedException) + { + + } + } + + try + { + connection.Item2.Cancel(); + connection.Item2.Dispose(); + } + catch (ObjectDisposedException) + { + + } + + ActiveConnections.Remove(connection); + } + + /// <summary> + /// Releases unmanaged and - optionally - managed resources. + /// </summary> + /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> + protected virtual void Dispose(bool dispose) + { + if (dispose) + { + lock (ActiveConnections) + { + foreach (var connection in ActiveConnections.ToList()) + { + DisposeConnection(connection); + } + } + } + } + + /// <summary> + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// </summary> + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + } + + public class WebSocketListenerState + { + public DateTime DateLastSendUtc { get; set; } + public long InitialDelayMs { get; set; } + public long IntervalMs { get; set; } + } +} diff --git a/MediaBrowser.Controller/Notifications/INotificationManager.cs b/MediaBrowser.Controller/Notifications/INotificationManager.cs index f9d264314..68cfd6ff1 100644 --- a/MediaBrowser.Controller/Notifications/INotificationManager.cs +++ b/MediaBrowser.Controller/Notifications/INotificationManager.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Controller.Entities; namespace MediaBrowser.Controller.Notifications { @@ -15,6 +16,8 @@ namespace MediaBrowser.Controller.Notifications /// <returns>Task.</returns> Task SendNotification(NotificationRequest request, CancellationToken cancellationToken); + Task SendNotification(NotificationRequest request, BaseItem relatedItem, CancellationToken cancellationToken); + /// <summary> /// Adds the parts. /// </summary> diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs index 3d05d2fca..4cb3e2bb6 100644 --- a/MediaBrowser.Controller/Persistence/IItemRepository.cs +++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs @@ -48,6 +48,8 @@ namespace MediaBrowser.Controller.Persistence /// <param name="cancellationToken">The cancellation token.</param> void SaveItems(List<BaseItem> items, CancellationToken cancellationToken); + void SaveImages(BaseItem item); + /// <summary> /// Retrieves the item. /// </summary> diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs index ee96a8c3b..071f8a096 100644 --- a/MediaBrowser.Controller/Playlists/Playlist.cs +++ b/MediaBrowser.Controller/Playlists/Playlist.cs @@ -73,7 +73,7 @@ namespace MediaBrowser.Controller.Playlists return 1; } - public override bool IsAuthorizedToDelete(User user) + public override bool IsAuthorizedToDelete(User user, List<Folder> allCollectionFolders) { return true; } diff --git a/MediaBrowser.Controller/Providers/IHasChangeMonitor.cs b/MediaBrowser.Controller/Providers/IHasChangeMonitor.cs deleted file mode 100644 index aa0b0e3c9..000000000 --- a/MediaBrowser.Controller/Providers/IHasChangeMonitor.cs +++ /dev/null @@ -1,17 +0,0 @@ -using MediaBrowser.Controller.Entities; -using System; - -namespace MediaBrowser.Controller.Providers -{ - public interface IHasChangeMonitor - { - /// <summary> - /// Determines whether the specified item has changed. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="directoryService">The directory service.</param> - /// <param name="date">The date.</param> - /// <returns><c>true</c> if the specified item has changed; otherwise, <c>false</c>.</returns> - bool HasChanged(IHasMetadata item, IDirectoryService directoryService, DateTime date); - } -} diff --git a/MediaBrowser.Controller/Providers/IMetadataService.cs b/MediaBrowser.Controller/Providers/IMetadataService.cs index 2d4873f7e..7b7bf166b 100644 --- a/MediaBrowser.Controller/Providers/IMetadataService.cs +++ b/MediaBrowser.Controller/Providers/IMetadataService.cs @@ -1,4 +1,5 @@ -using MediaBrowser.Controller.Entities; +using System; +using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using System.Threading; using System.Threading.Tasks; @@ -13,6 +14,7 @@ namespace MediaBrowser.Controller.Providers /// <param name="item">The item.</param> /// <returns><c>true</c> if this instance can refresh the specified item; otherwise, <c>false</c>.</returns> bool CanRefresh(IHasMetadata item); + bool CanRefreshPrimary(Type type); /// <summary> /// Refreshes the metadata. diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs index 77e6a7e40..c2cbda11d 100644 --- a/MediaBrowser.Controller/Providers/IProviderManager.cs +++ b/MediaBrowser.Controller/Providers/IProviderManager.cs @@ -119,16 +119,12 @@ namespace MediaBrowser.Controller.Providers /// <param name="item">The item.</param> /// <param name="updateType">Type of the update.</param> /// <returns>Task.</returns> - Task SaveMetadata(IHasMetadata item, ItemUpdateType updateType); + void SaveMetadata(IHasMetadata item, ItemUpdateType updateType); /// <summary> /// Saves the metadata. /// </summary> - /// <param name="item">The item.</param> - /// <param name="updateType">Type of the update.</param> - /// <param name="savers">The savers.</param> - /// <returns>Task.</returns> - Task SaveMetadata(IHasMetadata item, ItemUpdateType updateType, IEnumerable<string> savers); + void SaveMetadata(IHasMetadata item, ItemUpdateType updateType, IEnumerable<string> savers); /// <summary> /// Gets the metadata options. diff --git a/MediaBrowser.Controller/Providers/MetadataResult.cs b/MediaBrowser.Controller/Providers/MetadataResult.cs index 5ed55ea16..f35d41ca4 100644 --- a/MediaBrowser.Controller/Providers/MetadataResult.cs +++ b/MediaBrowser.Controller/Providers/MetadataResult.cs @@ -20,6 +20,7 @@ namespace MediaBrowser.Controller.Providers public bool HasMetadata { get; set; } public T Item { get; set; } public string ResultLanguage { get; set; } + public string Provider { get; set; } public bool QueriedById { get; set; } public void AddPerson(PersonInfo p) { diff --git a/MediaBrowser.Controller/Sync/ISyncManager.cs b/MediaBrowser.Controller/Sync/ISyncManager.cs index 910d697ec..0bf4b914f 100644 --- a/MediaBrowser.Controller/Sync/ISyncManager.cs +++ b/MediaBrowser.Controller/Sync/ISyncManager.cs @@ -91,8 +91,6 @@ namespace MediaBrowser.Controller.Sync /// </summary> List<SyncTarget> GetSyncTargets(string userId); - List<SyncTarget> GetSyncTargets(string userId, bool? supportsRemoteSync); - /// <summary> /// Supportses the synchronize. /// </summary> diff --git a/MediaBrowser.Controller/Sync/ISyncProvider.cs b/MediaBrowser.Controller/Sync/ISyncProvider.cs index 2f60e124e..baee1a52f 100644 --- a/MediaBrowser.Controller/Sync/ISyncProvider.cs +++ b/MediaBrowser.Controller/Sync/ISyncProvider.cs @@ -11,8 +11,6 @@ namespace MediaBrowser.Controller.Sync /// <value>The name.</value> string Name { get; } - bool SupportsRemoteSync { get; } - /// <summary> /// Gets the synchronize targets. /// </summary> |
