diff options
Diffstat (limited to 'MediaBrowser.Controller/Entities')
64 files changed, 0 insertions, 13849 deletions
diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs deleted file mode 100644 index 00fac1eabd..0000000000 --- a/MediaBrowser.Controller/Entities/AggregateFolder.cs +++ /dev/null @@ -1,225 +0,0 @@ -using MediaBrowser.Controller.IO; -using MediaBrowser.Controller.Library; -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Specialized folder that can have items added to it's children by external entities. - /// Used for our RootFolder so plug-ins can add items. - /// </summary> - public class AggregateFolder : Folder - { - public AggregateFolder() - { - PhysicalLocationsList = EmptyStringArray; - } - - [IgnoreDataMember] - public override bool IsPhysicalRoot - { - get { return true; } - } - - public override bool CanDelete() - { - return false; - } - - [IgnoreDataMember] - public override bool SupportsPlayedStatus - { - get - { - return false; - } - } - - /// <summary> - /// The _virtual children - /// </summary> - private readonly ConcurrentBag<BaseItem> _virtualChildren = new ConcurrentBag<BaseItem>(); - - /// <summary> - /// Gets the virtual children. - /// </summary> - /// <value>The virtual children.</value> - public ConcurrentBag<BaseItem> VirtualChildren - { - get { return _virtualChildren; } - } - - [IgnoreDataMember] - public override string[] PhysicalLocations - { - get - { - return PhysicalLocationsList; - } - } - - public string[] PhysicalLocationsList { get; set; } - - protected override FileSystemMetadata[] GetFileSystemChildren(IDirectoryService directoryService) - { - return CreateResolveArgs(directoryService, true).FileSystemChildren; - } - - private Guid[] _childrenIds = null; - private readonly object _childIdsLock = new object(); - protected override List<BaseItem> LoadChildren() - { - lock (_childIdsLock) - { - if (_childrenIds == null || _childrenIds.Length == 0) - { - var list = base.LoadChildren(); - _childrenIds = list.Select(i => i.Id).ToArray(); - return list; - } - - return _childrenIds.Select(LibraryManager.GetItemById).Where(i => i != null).ToList(); - } - } - - private void ClearCache() - { - lock (_childIdsLock) - { - _childrenIds = null; - } - } - - private bool _requiresRefresh; - public override bool RequiresRefresh() - { - var changed = base.RequiresRefresh() || _requiresRefresh; - - if (!changed) - { - var locations = PhysicalLocations; - - var newLocations = CreateResolveArgs(new DirectoryService(Logger, FileSystem), false).PhysicalLocations; - - if (!locations.SequenceEqual(newLocations)) - { - changed = true; - } - } - - return changed; - } - - public override bool BeforeMetadataRefresh() - { - ClearCache(); - - var changed = base.BeforeMetadataRefresh() || _requiresRefresh; - _requiresRefresh = false; - return changed; - } - - private ItemResolveArgs CreateResolveArgs(IDirectoryService directoryService, bool setPhysicalLocations) - { - ClearCache(); - - var path = ContainingFolderPath; - - var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, directoryService) - { - FileInfo = FileSystem.GetDirectoryInfo(path), - Path = path, - Parent = GetParent() as Folder - }; - - // Gather child folder and files - if (args.IsDirectory) - { - var isPhysicalRoot = args.IsPhysicalRoot; - - // When resolving the root, we need it's grandchildren (children of user views) - var flattenFolderDepth = isPhysicalRoot ? 2 : 0; - - var files = FileData.GetFilteredFileSystemEntries(directoryService, args.Path, FileSystem, Logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: isPhysicalRoot || args.IsVf); - - // Need to remove subpaths that may have been resolved from shortcuts - // Example: if \\server\movies exists, then strip out \\server\movies\action - if (isPhysicalRoot) - { - files = LibraryManager.NormalizeRootPathList(files).ToArray(); - } - - args.FileSystemChildren = files; - } - - _requiresRefresh = _requiresRefresh || !args.PhysicalLocations.SequenceEqual(PhysicalLocations); - if (setPhysicalLocations) - { - PhysicalLocationsList = args.PhysicalLocations; - } - - return args; - } - - protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService) - { - return base.GetNonCachedChildren(directoryService).Concat(_virtualChildren); - } - - protected override async Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService) - { - ClearCache(); - - await base.ValidateChildrenInternal(progress, cancellationToken, recursive, refreshChildMetadata, refreshOptions, directoryService) - .ConfigureAwait(false); - - ClearCache(); - } - - /// <summary> - /// Adds the virtual child. - /// </summary> - /// <param name="child">The child.</param> - /// <exception cref="System.ArgumentNullException"></exception> - public void AddVirtualChild(BaseItem child) - { - if (child == null) - { - throw new ArgumentNullException(); - } - - _virtualChildren.Add(child); - } - - /// <summary> - /// Finds the virtual child. - /// </summary> - /// <param name="id">The id.</param> - /// <returns>BaseItem.</returns> - /// <exception cref="System.ArgumentNullException">id</exception> - public BaseItem FindVirtualChild(Guid id) - { - if (id == Guid.Empty) - { - throw new ArgumentNullException("id"); - } - - foreach (var child in _virtualChildren) - { - if (child.Id == id) - { - return child; - } - } - return null; - } - } -} diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs deleted file mode 100644 index 16fd75d2e9..0000000000 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ /dev/null @@ -1,296 +0,0 @@ -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.MediaInfo; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Threading; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Controller.Entities.Audio -{ - /// <summary> - /// Class Audio - /// </summary> - public class Audio : BaseItem, - IHasAlbumArtist, - IHasArtist, - IHasMusicGenres, - IHasLookupInfo<SongInfo>, - IHasMediaSources - { - /// <summary> - /// Gets or sets the artist. - /// </summary> - /// <value>The artist.</value> - [IgnoreDataMember] - public string[] Artists { get; set; } - - [IgnoreDataMember] - public string[] AlbumArtists { get; set; } - - [IgnoreDataMember] - public override bool EnableRefreshOnDateModifiedChange - { - get { return true; } - } - - public Audio() - { - Artists = EmptyStringArray; - AlbumArtists = EmptyStringArray; - } - - public override double? GetDefaultPrimaryImageAspectRatio() - { - return 1; - } - - [IgnoreDataMember] - public override bool SupportsPlayedStatus - { - get - { - return true; - } - } - - [IgnoreDataMember] - public override bool SupportsPeople - { - get { return false; } - } - - [IgnoreDataMember] - public override bool SupportsAddingToPlaylist - { - get { return true; } - } - - [IgnoreDataMember] - public override bool SupportsInheritedParentImages - { - get { return true; } - } - - [IgnoreDataMember] - protected override bool SupportsOwnedItems - { - get - { - return false; - } - } - - [IgnoreDataMember] - public override Folder LatestItemsIndexContainer - { - get - { - return AlbumEntity; - } - } - - public override bool CanDownload() - { - var locationType = LocationType; - return locationType != LocationType.Remote && - locationType != LocationType.Virtual; - } - - [IgnoreDataMember] - public string[] AllArtists - { - get - { - var list = new string[AlbumArtists.Length + Artists.Length]; - - var index = 0; - foreach (var artist in AlbumArtists) - { - list[index] = artist; - index++; - } - foreach (var artist in Artists) - { - list[index] = artist; - index++; - } - - return list; - - } - } - - [IgnoreDataMember] - public MusicAlbum AlbumEntity - { - get { return FindParent<MusicAlbum>(); } - } - - /// <summary> - /// Gets the type of the media. - /// </summary> - /// <value>The type of the media.</value> - [IgnoreDataMember] - public override string MediaType - { - get - { - return Model.Entities.MediaType.Audio; - } - } - - /// <summary> - /// Creates the name of the sort. - /// </summary> - /// <returns>System.String.</returns> - protected override string CreateSortName() - { - return (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("0000 - ") : "") - + (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name; - } - - public override List<string> GetUserDataKeys() - { - var list = base.GetUserDataKeys(); - - var songKey = IndexNumber.HasValue ? IndexNumber.Value.ToString("0000") : string.Empty; - - - if (ParentIndexNumber.HasValue) - { - songKey = ParentIndexNumber.Value.ToString("0000") + "-" + songKey; - } - songKey += Name; - - 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); - - return list; - } - - public override UnratedItem GetBlockUnratedType() - { - if (SourceType == SourceType.Library) - { - return UnratedItem.Music; - } - return base.GetBlockUnratedType(); - } - - public List<MediaStream> GetMediaStreams() - { - return MediaSourceManager.GetMediaStreams(new MediaStreamQuery - { - ItemId = Id - }); - } - - public List<MediaStream> GetMediaStreams(MediaStreamType type) - { - return MediaSourceManager.GetMediaStreams(new MediaStreamQuery - { - ItemId = Id, - Type = type - }); - } - - public SongInfo GetLookupInfo() - { - var info = GetItemLookupInfo<SongInfo>(); - - info.AlbumArtists = AlbumArtists; - info.Album = Album; - info.Artists = Artists; - - return info; - } - - public virtual List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution) - { - if (SourceType == SourceType.Channel) - { - var sources = ChannelManager.GetStaticMediaSources(this, CancellationToken.None) - .ToList(); - - if (sources.Count > 0) - { - return sources; - } - - var list = new List<MediaSourceInfo> - { - GetVersionInfo(this, enablePathSubstitution) - }; - - foreach (var mediaSource in list) - { - if (string.IsNullOrWhiteSpace(mediaSource.Path)) - { - mediaSource.Type = MediaSourceType.Placeholder; - } - } - - return list; - } - - var result = new List<MediaSourceInfo> - { - GetVersionInfo(this, enablePathSubstitution) - }; - - return result; - } - - private static MediaSourceInfo GetVersionInfo(Audio i, bool enablePathSubstituion) - { - var locationType = i.LocationType; - - var info = new MediaSourceInfo - { - Id = i.Id.ToString("N"), - Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File, - MediaStreams = MediaSourceManager.GetMediaStreams(i.Id), - Name = i.Name, - Path = enablePathSubstituion ? GetMappedPath(i, i.Path, locationType) : i.Path, - RunTimeTicks = i.RunTimeTicks, - Container = i.Container, - Size = i.Size - }; - - if (info.Protocol == MediaProtocol.File) - { - info.ETag = i.DateModified.Ticks.ToString(CultureInfo.InvariantCulture).GetMD5().ToString("N"); - } - - if (string.IsNullOrEmpty(info.Container)) - { - if (!string.IsNullOrWhiteSpace(i.Path) && locationType != LocationType.Remote && locationType != LocationType.Virtual) - { - info.Container = System.IO.Path.GetExtension(i.Path).TrimStart('.'); - } - } - - info.Bitrate = i.TotalBitrate; - info.InferTotalBitrate(); - - return info; - } - } -} diff --git a/MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs b/MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs deleted file mode 100644 index 1b717b900a..0000000000 --- a/MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs +++ /dev/null @@ -1,31 +0,0 @@ -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Controller.Entities.Audio -{ - public class AudioPodcast : Audio, IHasLookupInfo<SongInfo> - { - [IgnoreDataMember] - public override bool SupportsPositionTicksResume - { - get - { - return true; - } - } - - [IgnoreDataMember] - public override bool SupportsPlayedStatus - { - get - { - return true; - } - } - - public override double? GetDefaultPrimaryImageAspectRatio() - { - return 1; - } - } -} diff --git a/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs b/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs deleted file mode 100644 index b2dedada47..0000000000 --- a/MediaBrowser.Controller/Entities/Audio/IHasAlbumArtist.cs +++ /dev/null @@ -1,15 +0,0 @@ - -namespace MediaBrowser.Controller.Entities.Audio -{ - public interface IHasAlbumArtist - { - string[] AlbumArtists { get; set; } - } - - public interface IHasArtist - { - string[] AllArtists { get; } - - string[] Artists { get; set; } - } -} diff --git a/MediaBrowser.Controller/Entities/Audio/IHasMusicGenres.cs b/MediaBrowser.Controller/Entities/Audio/IHasMusicGenres.cs deleted file mode 100644 index fdf939e359..0000000000 --- a/MediaBrowser.Controller/Entities/Audio/IHasMusicGenres.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Collections.Generic; - -namespace MediaBrowser.Controller.Entities.Audio -{ - public interface IHasMusicGenres - { - List<string> Genres { get; } - } -} diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs deleted file mode 100644 index acda9ae02b..0000000000 --- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs +++ /dev/null @@ -1,272 +0,0 @@ -using System; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Users; -using System.Collections.Generic; -using System.Linq; -using MediaBrowser.Model.Serialization; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Dto; -using MediaBrowser.Controller.Library; - -namespace MediaBrowser.Controller.Entities.Audio -{ - /// <summary> - /// Class MusicAlbum - /// </summary> - public class MusicAlbum : Folder, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo<AlbumInfo>, IMetadataContainer - { - public string[] AlbumArtists { get; set; } - public string[] Artists { get; set; } - - public MusicAlbum() - { - Artists = EmptyStringArray; - AlbumArtists = EmptyStringArray; - } - - [IgnoreDataMember] - public override bool SupportsAddingToPlaylist - { - get { return true; } - } - - [IgnoreDataMember] - public override bool SupportsInheritedParentImages - { - get { return true; } - } - - [IgnoreDataMember] - public MusicArtist MusicArtist - { - get { return GetMusicArtist(new DtoOptions(true)); } - } - - public MusicArtist GetMusicArtist(DtoOptions options) - { - var parents = GetParents(); - foreach (var parent in parents) - { - var artist = parent as MusicArtist; - if (artist != null) - { - return artist; - } - } - - var name = AlbumArtist; - if (!string.IsNullOrWhiteSpace(name)) - { - return LibraryManager.GetArtist(name, options); - } - return null; - } - - [IgnoreDataMember] - public override bool SupportsPlayedStatus - { - get - { - return false; - } - } - - [IgnoreDataMember] - public override bool SupportsCumulativeRunTimeTicks - { - get - { - return true; - } - } - - [IgnoreDataMember] - public string[] AllArtists - { - get - { - var list = new string[AlbumArtists.Length + Artists.Length]; - - var index = 0; - foreach (var artist in AlbumArtists) - { - list[index] = artist; - index++; - } - foreach (var artist in Artists) - { - list[index] = artist; - index++; - } - - return list; - } - } - - [IgnoreDataMember] - public string AlbumArtist - { - get { return AlbumArtists.Length == 0 ? null : AlbumArtists[0]; } - } - - [IgnoreDataMember] - public override bool SupportsPeople - { - get { return false; } - } - - /// <summary> - /// Gets the tracks. - /// </summary> - /// <value>The tracks.</value> - [IgnoreDataMember] - public IEnumerable<BaseItem> Tracks - { - get - { - return GetRecursiveChildren(i => i is Audio); - } - } - - protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user) - { - return Tracks; - } - - public override double? GetDefaultPrimaryImageAspectRatio() - { - return 1; - } - - public override List<string> GetUserDataKeys() - { - var list = base.GetUserDataKeys(); - - var albumArtist = AlbumArtist; - if (!string.IsNullOrWhiteSpace(albumArtist)) - { - list.Insert(0, albumArtist + "-" + Name); - } - - var id = this.GetProviderId(MetadataProviders.MusicBrainzAlbum); - - if (!string.IsNullOrWhiteSpace(id)) - { - list.Insert(0, "MusicAlbum-Musicbrainz-" + id); - } - - id = this.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup); - - if (!string.IsNullOrWhiteSpace(id)) - { - list.Insert(0, "MusicAlbum-MusicBrainzReleaseGroup-" + id); - } - - return list; - } - - protected override bool GetBlockUnratedValue(UserPolicy config) - { - return config.BlockUnratedItems.Contains(UnratedItem.Music); - } - - public override UnratedItem GetBlockUnratedType() - { - return UnratedItem.Music; - } - - public AlbumInfo GetLookupInfo() - { - var id = GetItemLookupInfo<AlbumInfo>(); - - id.AlbumArtists = AlbumArtists; - - var artist = GetMusicArtist(new DtoOptions(false)); - - if (artist != null) - { - id.ArtistProviderIds = artist.ProviderIds; - } - - id.SongInfos = GetRecursiveChildren(i => i is Audio) - .Cast<Audio>() - .Select(i => i.GetLookupInfo()) - .ToList(); - - var album = id.SongInfos - .Select(i => i.Album) - .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); - - if (!string.IsNullOrWhiteSpace(album)) - { - id.Name = album; - } - - return id; - } - - public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken) - { - var items = GetRecursiveChildren(); - - var totalItems = items.Count; - var numComplete = 0; - - var childUpdateType = ItemUpdateType.None; - - // Refresh songs - foreach (var item in items) - { - cancellationToken.ThrowIfCancellationRequested(); - - var updateType = await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); - childUpdateType = childUpdateType | updateType; - - numComplete++; - double percent = numComplete; - percent /= totalItems; - progress.Report(percent * 95); - } - - var parentRefreshOptions = refreshOptions; - if (childUpdateType > ItemUpdateType.None) - { - parentRefreshOptions = new MetadataRefreshOptions(refreshOptions); - parentRefreshOptions.MetadataRefreshMode = MetadataRefreshMode.FullRefresh; - } - - // Refresh current item - await RefreshMetadata(parentRefreshOptions, cancellationToken).ConfigureAwait(false); - - if (!refreshOptions.IsAutomated) - { - await RefreshArtists(refreshOptions, cancellationToken).ConfigureAwait(false); - } - } - - private async Task RefreshArtists(MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken) - { - var all = AllArtists; - foreach (var i in all) - { - // This should not be necessary but we're seeing some cases of it - if (string.IsNullOrWhiteSpace(i)) - { - continue; - } - - var artist = LibraryManager.GetArtist(i); - - if (!artist.IsAccessedByName) - { - continue; - } - - await artist.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); - } - } - } -} diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs deleted file mode 100644 index 19fe68e25f..0000000000 --- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs +++ /dev/null @@ -1,345 +0,0 @@ -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Users; -using System; -using System.Collections.Generic; -using System.Linq; -using MediaBrowser.Model.Serialization; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.Extensions; -using MediaBrowser.Model.Extensions; - -namespace MediaBrowser.Controller.Entities.Audio -{ - /// <summary> - /// Class MusicArtist - /// </summary> - public class MusicArtist : Folder, IMetadataContainer, IItemByName, IHasMusicGenres, IHasDualAccess, IHasLookupInfo<ArtistInfo> - { - [IgnoreDataMember] - public bool IsAccessedByName - { - get { return ParentId == Guid.Empty; } - } - - [IgnoreDataMember] - public override bool IsFolder - { - get - { - return !IsAccessedByName; - } - } - - [IgnoreDataMember] - public override bool SupportsInheritedParentImages - { - get - { - return false; - } - } - - [IgnoreDataMember] - public override bool SupportsCumulativeRunTimeTicks - { - get - { - return true; - } - } - - [IgnoreDataMember] - public override bool IsDisplayedAsFolder - { - get - { - return true; - } - } - - [IgnoreDataMember] - public override bool SupportsAddingToPlaylist - { - get { return true; } - } - - [IgnoreDataMember] - public override bool SupportsPlayedStatus - { - get - { - return false; - } - } - - public override double? GetDefaultPrimaryImageAspectRatio() - { - return 1; - } - - public override bool CanDelete() - { - return !IsAccessedByName; - } - - public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query) - { - if (query.IncludeItemTypes.Length == 0) - { - query.IncludeItemTypes = new[] { typeof(Audio).Name, typeof(MusicVideo).Name, typeof(MusicAlbum).Name }; - query.ArtistIds = new[] { Id.ToString("N") }; - } - - return LibraryManager.GetItemList(query); - } - - [IgnoreDataMember] - public override IEnumerable<BaseItem> Children - { - get - { - if (IsAccessedByName) - { - return new List<BaseItem>(); - } - - return base.Children; - } - } - - public override int GetChildCount(User user) - { - if (IsAccessedByName) - { - return 0; - } - return base.GetChildCount(user); - } - - public override bool IsSaveLocalMetadataEnabled() - { - if (IsAccessedByName) - { - return true; - } - - return base.IsSaveLocalMetadataEnabled(); - } - - private readonly Task _cachedTask = Task.FromResult(true); - protected override Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService) - { - if (IsAccessedByName) - { - // Should never get in here anyway - return _cachedTask; - } - - return base.ValidateChildrenInternal(progress, cancellationToken, recursive, refreshChildMetadata, refreshOptions, directoryService); - } - - public override List<string> GetUserDataKeys() - { - var list = base.GetUserDataKeys(); - - list.InsertRange(0, GetUserDataKeys(this)); - return list; - } - - /// <summary> - /// Returns the folder containing the item. - /// If the item is a folder, it returns the folder itself - /// </summary> - /// <value>The containing folder path.</value> - [IgnoreDataMember] - public override string ContainingFolderPath - { - get - { - return Path; - } - } - - /// <summary> - /// Gets a value indicating whether this instance is owned item. - /// </summary> - /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public override bool IsOwnedItem - { - get - { - return false; - } - } - - /// <summary> - /// Gets the user data key. - /// </summary> - /// <param name="item">The item.</param> - /// <returns>System.String.</returns> - private static List<string> GetUserDataKeys(MusicArtist item) - { - var list = new List<string>(); - var id = item.GetProviderId(MetadataProviders.MusicBrainzArtist); - - if (!string.IsNullOrEmpty(id)) - { - list.Add("Artist-Musicbrainz-" + id); - } - - list.Add("Artist-" + (item.Name ?? string.Empty).RemoveDiacritics()); - return list; - } - public override string CreatePresentationUniqueKey() - { - return "Artist-" + (Name ?? string.Empty).RemoveDiacritics(); - } - protected override bool GetBlockUnratedValue(UserPolicy config) - { - return config.BlockUnratedItems.Contains(UnratedItem.Music); - } - - public override UnratedItem GetBlockUnratedType() - { - return UnratedItem.Music; - } - - public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken) - { - var items = GetRecursiveChildren(); - - var totalItems = items.Count; - var numComplete = 0; - - var childUpdateType = ItemUpdateType.None; - - // Refresh songs - foreach (var item in items) - { - if (!(item is Audio)) - { - continue; - } - - cancellationToken.ThrowIfCancellationRequested(); - - var updateType = await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); - childUpdateType = childUpdateType | updateType; - - numComplete++; - double percent = numComplete; - percent /= totalItems; - progress.Report(percent * 100); - } - - var parentRefreshOptions = refreshOptions; - if (childUpdateType > ItemUpdateType.None) - { - parentRefreshOptions = new MetadataRefreshOptions(refreshOptions); - parentRefreshOptions.MetadataRefreshMode = MetadataRefreshMode.FullRefresh; - } - - // Refresh current item - await RefreshMetadata(parentRefreshOptions, cancellationToken).ConfigureAwait(false); - - // Refresh all non-songs - foreach (var item in items) - { - if (item is Audio) - { - continue; - } - - cancellationToken.ThrowIfCancellationRequested(); - - var updateType = await item.RefreshMetadata(parentRefreshOptions, cancellationToken).ConfigureAwait(false); - - numComplete++; - double percent = numComplete; - percent /= totalItems; - progress.Report(percent * 100); - } - } - - public ArtistInfo GetLookupInfo() - { - var info = GetItemLookupInfo<ArtistInfo>(); - - info.SongInfos = GetRecursiveChildren(i => i is Audio) - .Cast<Audio>() - .Select(i => i.GetLookupInfo()) - .ToList(); - - return info; - } - - [IgnoreDataMember] - public override bool SupportsPeople - { - get - { - return false; - } - } - - public static string GetPath(string name) - { - return GetPath(name, true); - } - - public static string GetPath(string name, bool normalizeName) - { - // Trim the period at the end because windows will have a hard time with that - var validName = normalizeName ? - FileSystem.GetValidFilename(name).Trim().TrimEnd('.') : - name; - - return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.ArtistsPath, validName); - } - - private string GetRebasedPath() - { - return GetPath(System.IO.Path.GetFileName(Path), false); - } - - public override bool RequiresRefresh() - { - if (IsAccessedByName) - { - var newPath = GetRebasedPath(); - if (!string.Equals(Path, newPath, StringComparison.Ordinal)) - { - Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath); - return true; - } - } - return base.RequiresRefresh(); - } - - /// <summary> - /// This is called before any metadata refresh and returns true or false indicating if changes were made - /// </summary> - public override bool BeforeMetadataRefresh() - { - var hasChanges = base.BeforeMetadataRefresh(); - - if (IsAccessedByName) - { - var newPath = GetRebasedPath(); - if (!string.Equals(Path, newPath, StringComparison.Ordinal)) - { - Path = newPath; - hasChanges = true; - } - } - - return hasChanges; - } - } -} diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs deleted file mode 100644 index 02e6520488..0000000000 --- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs +++ /dev/null @@ -1,158 +0,0 @@ -using System; -using System.Collections.Generic; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.Extensions; -using MediaBrowser.Model.Extensions; - -namespace MediaBrowser.Controller.Entities.Audio -{ - /// <summary> - /// Class MusicGenre - /// </summary> - public class MusicGenre : BaseItem, IItemByName - { - public override List<string> GetUserDataKeys() - { - var list = base.GetUserDataKeys(); - - list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics()); - return list; - } - public override string CreatePresentationUniqueKey() - { - return GetUserDataKeys()[0]; - } - - [IgnoreDataMember] - public override bool SupportsAddingToPlaylist - { - get { return true; } - } - - [IgnoreDataMember] - public override bool SupportsAncestors - { - get - { - return false; - } - } - - [IgnoreDataMember] - public override bool IsDisplayedAsFolder - { - get - { - return true; - } - } - - /// <summary> - /// Returns the folder containing the item. - /// If the item is a folder, it returns the folder itself - /// </summary> - /// <value>The containing folder path.</value> - [IgnoreDataMember] - public override string ContainingFolderPath - { - get - { - return Path; - } - } - - public override double? GetDefaultPrimaryImageAspectRatio() - { - return 1; - } - - public override bool CanDelete() - { - return false; - } - - public override bool IsSaveLocalMetadataEnabled() - { - return true; - } - - /// <summary> - /// Gets a value indicating whether this instance is owned item. - /// </summary> - /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public override bool IsOwnedItem - { - get - { - return false; - } - } - - [IgnoreDataMember] - public override bool SupportsPeople - { - get - { - return false; - } - } - - public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query) - { - query.GenreIds = new[] { Id.ToString("N") }; - query.IncludeItemTypes = new[] { typeof(MusicVideo).Name, typeof(Audio).Name, typeof(MusicAlbum).Name, typeof(MusicArtist).Name }; - - return LibraryManager.GetItemList(query); - } - - public static string GetPath(string name) - { - return GetPath(name, true); - } - - public static string GetPath(string name, bool normalizeName) - { - // Trim the period at the end because windows will have a hard time with that - var validName = normalizeName ? - FileSystem.GetValidFilename(name).Trim().TrimEnd('.') : - name; - - return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.MusicGenrePath, validName); - } - - private string GetRebasedPath() - { - return GetPath(System.IO.Path.GetFileName(Path), false); - } - - public override bool RequiresRefresh() - { - var newPath = GetRebasedPath(); - if (!string.Equals(Path, newPath, StringComparison.Ordinal)) - { - Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath); - return true; - } - return base.RequiresRefresh(); - } - - /// <summary> - /// This is called before any metadata refresh and returns true or false indicating if changes were made - /// </summary> - public override bool BeforeMetadataRefresh() - { - var hasChanges = base.BeforeMetadataRefresh(); - - var newPath = GetRebasedPath(); - if (!string.Equals(Path, newPath, StringComparison.Ordinal)) - { - Path = newPath; - hasChanges = true; - } - - return hasChanges; - } - } -} diff --git a/MediaBrowser.Controller/Entities/AudioBook.cs b/MediaBrowser.Controller/Entities/AudioBook.cs deleted file mode 100644 index 374bb21f74..0000000000 --- a/MediaBrowser.Controller/Entities/AudioBook.cs +++ /dev/null @@ -1,71 +0,0 @@ -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, IHasLookupInfo<SongInfo> - { - [IgnoreDataMember] - public override bool SupportsPositionTicksResume - { - get - { - return true; - } - } - - [IgnoreDataMember] - public override bool SupportsPlayedStatus - { - get - { - return true; - } - } - - [IgnoreDataMember] - public string SeriesPresentationUniqueKey { get; set; } - [IgnoreDataMember] - public string SeriesName { get; set; } - [IgnoreDataMember] - public Guid? SeriesId { get; set; } - - public string FindSeriesSortName() - { - return SeriesName; - } - public string FindSeriesName() - { - return SeriesName; - } - public string FindSeriesPresentationUniqueKey() - { - return SeriesPresentationUniqueKey; - } - - public override double? GetDefaultPrimaryImageAspectRatio() - { - return null; - } - - public Guid? FindSeriesId() - { - return SeriesId; - } - - public override bool CanDownload() - { - var locationType = LocationType; - return locationType != LocationType.Remote && - locationType != LocationType.Virtual; - } - - public override UnratedItem GetBlockUnratedType() - { - return UnratedItem.Book; - } - } -} diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs deleted file mode 100644 index 98899253e1..0000000000 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ /dev/null @@ -1,2600 +0,0 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.Channels; -using MediaBrowser.Controller.Collections; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Drawing; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Library; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Users; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -using MediaBrowser.Controller.Dto; -using MediaBrowser.Controller.Extensions; -using MediaBrowser.Controller.IO; -using MediaBrowser.Controller.MediaEncoding; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Extensions; -using MediaBrowser.Model.Globalization; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.LiveTv; -using MediaBrowser.Model.Providers; -using MediaBrowser.Model.Querying; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Class BaseItem - /// </summary> - public abstract class BaseItem : IHasMetadata, IHasLookupInfo<ItemLookupInfo> - { - protected static Guid[] EmptyGuidArray = new Guid[] { }; - protected static MetadataFields[] EmptyMetadataFieldsArray = new MetadataFields[] { }; - protected static string[] EmptyStringArray = new string[] { }; - protected static MediaUrl[] EmptyMediaUrlArray = new MediaUrl[] { }; - protected static ItemImageInfo[] EmptyItemImageInfoArray = new ItemImageInfo[] { }; - public static readonly LinkedChild[] EmptyLinkedChildArray = new LinkedChild[] { }; - - protected BaseItem() - { - ThemeSongIds = EmptyGuidArray; - ThemeVideoIds = EmptyGuidArray; - Tags = EmptyStringArray; - Genres = new List<string>(); - Studios = EmptyStringArray; - ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - LockedFields = EmptyMetadataFieldsArray; - ImageInfos = EmptyItemImageInfoArray; - ProductionLocations = EmptyStringArray; - } - - public static readonly char[] SlugReplaceChars = { '?', '/', '&' }; - public static char SlugChar = '-'; - - /// <summary> - /// The supported image extensions - /// </summary> - public static readonly string[] SupportedImageExtensions = { ".png", ".jpg", ".jpeg", ".tbn", ".gif" }; - - public static readonly List<string> SupportedImageExtensionsList = SupportedImageExtensions.ToList(); - - /// <summary> - /// The trailer folder name - /// </summary> - public static string TrailerFolderName = "trailers"; - public static string ThemeSongsFolderName = "theme-music"; - public static string ThemeSongFilename = "theme"; - public static string ThemeVideosFolderName = "backdrops"; - - [IgnoreDataMember] - public Guid[] ThemeSongIds { get; set; } - [IgnoreDataMember] - public Guid[] ThemeVideoIds { get; set; } - - [IgnoreDataMember] - public string PreferredMetadataCountryCode { get; set; } - [IgnoreDataMember] - public string PreferredMetadataLanguage { get; set; } - - public long? Size { get; set; } - public string Container { get; set; } - - [IgnoreDataMember] - public string Tagline { get; set; } - - [IgnoreDataMember] - public virtual ItemImageInfo[] ImageInfos { get; set; } - - [IgnoreDataMember] - public bool IsVirtualItem { get; set; } - - /// <summary> - /// Gets or sets the album. - /// </summary> - /// <value>The album.</value> - [IgnoreDataMember] - public string Album { get; set; } - - /// <summary> - /// Gets or sets the channel identifier. - /// </summary> - /// <value>The channel identifier.</value> - [IgnoreDataMember] - public string ChannelId { get; set; } - - [IgnoreDataMember] - public virtual bool SupportsAddingToPlaylist - { - get - { - return false; - } - } - - [IgnoreDataMember] - public virtual bool AlwaysScanInternalMetadataPath - { - get { return false; } - } - - /// <summary> - /// Gets a value indicating whether this instance is in mixed folder. - /// </summary> - /// <value><c>true</c> if this instance is in mixed folder; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public bool IsInMixedFolder { get; set; } - - [IgnoreDataMember] - public virtual bool SupportsPlayedStatus - { - get - { - return false; - } - } - - [IgnoreDataMember] - public virtual bool SupportsPositionTicksResume - { - get - { - return false; - } - } - - [IgnoreDataMember] - public virtual bool SupportsRemoteImageDownloading - { - get - { - return true; - } - } - - private string _name; - /// <summary> - /// Gets or sets the name. - /// </summary> - /// <value>The name.</value> - [IgnoreDataMember] - public virtual string Name - { - get - { - return _name; - } - set - { - _name = value; - - // lazy load this again - _sortName = null; - } - } - - [IgnoreDataMember] - public bool IsUnaired - { - get { return PremiereDate.HasValue && PremiereDate.Value.ToLocalTime().Date >= DateTime.Now.Date; } - } - - [IgnoreDataMember] - public int? TotalBitrate { get; set; } - [IgnoreDataMember] - public ExtraType? ExtraType { get; set; } - - [IgnoreDataMember] - public bool IsThemeMedia - { - get - { - return ExtraType.HasValue && (ExtraType.Value == Model.Entities.ExtraType.ThemeSong || ExtraType.Value == Model.Entities.ExtraType.ThemeVideo); - } - } - - [IgnoreDataMember] - public string OriginalTitle { get; set; } - - /// <summary> - /// Gets or sets the id. - /// </summary> - /// <value>The id.</value> - [IgnoreDataMember] - public Guid Id { get; set; } - - [IgnoreDataMember] - public Guid OwnerId { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether this instance is hd. - /// </summary> - /// <value><c>true</c> if this instance is hd; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public bool? IsHD { get; set; } - - /// <summary> - /// Gets or sets the audio. - /// </summary> - /// <value>The audio.</value> - [IgnoreDataMember] - public ProgramAudio? Audio { get; set; } - - /// <summary> - /// Return the id that should be used to key display prefs for this item. - /// Default is based on the type for everything except actual generic folders. - /// </summary> - /// <value>The display prefs id.</value> - [IgnoreDataMember] - public virtual Guid DisplayPreferencesId - { - get - { - var thisType = GetType(); - return thisType == typeof(Folder) ? Id : thisType.FullName.GetMD5(); - } - } - - /// <summary> - /// Gets or sets the path. - /// </summary> - /// <value>The path.</value> - [IgnoreDataMember] - public virtual string Path { get; set; } - - [IgnoreDataMember] - public virtual SourceType SourceType - { - get - { - if (!string.IsNullOrWhiteSpace(ChannelId)) - { - return SourceType.Channel; - } - - return SourceType.Library; - } - } - - /// <summary> - /// Returns the folder containing the item. - /// If the item is a folder, it returns the folder itself - /// </summary> - [IgnoreDataMember] - public virtual string ContainingFolderPath - { - get - { - if (IsFolder) - { - return Path; - } - - return FileSystem.GetDirectoryName(Path); - } - } - - /// <summary> - /// Gets or sets the name of the service. - /// </summary> - /// <value>The name of the service.</value> - [IgnoreDataMember] - public string ServiceName { get; set; } - - /// <summary> - /// If this content came from an external service, the id of the content on that service - /// </summary> - [IgnoreDataMember] - public string ExternalId { get; set; } - - [IgnoreDataMember] - public string ExternalSeriesId { get; set; } - - /// <summary> - /// Gets or sets the etag. - /// </summary> - /// <value>The etag.</value> - [IgnoreDataMember] - public string ExternalEtag { get; set; } - - [IgnoreDataMember] - public virtual bool IsHidden - { - get - { - return false; - } - } - - [IgnoreDataMember] - public virtual bool IsOwnedItem - { - 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 - // 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); - } - - /// <summary> - /// Gets or sets the type of the location. - /// </summary> - /// <value>The type of the location.</value> - [IgnoreDataMember] - public virtual LocationType LocationType - { - get - { - //if (IsOffline) - //{ - // return LocationType.Offline; - //} - - if (string.IsNullOrWhiteSpace(Path)) - { - if (SourceType == SourceType.Channel) - { - return LocationType.Remote; - } - - return LocationType.Virtual; - } - - return FileSystem.IsPathFile(Path) ? LocationType.FileSystem : LocationType.Remote; - } - } - - [IgnoreDataMember] - public virtual bool SupportsLocalMetadata - { - get - { - if (SourceType == SourceType.Channel) - { - return false; - } - - var locationType = LocationType; - - return locationType != LocationType.Remote && locationType != LocationType.Virtual; - } - } - - [IgnoreDataMember] - public virtual string FileNameWithoutExtension - { - get - { - if (LocationType == LocationType.FileSystem) - { - return System.IO.Path.GetFileNameWithoutExtension(Path); - } - - return null; - } - } - - [IgnoreDataMember] - public virtual bool EnableAlphaNumericSorting - { - get - { - return true; - } - } - - private List<Tuple<StringBuilder, bool>> GetSortChunks(string s1) - { - var list = new List<Tuple<StringBuilder, bool>>(); - - int thisMarker = 0, thisNumericChunk = 0; - - while (thisMarker < s1.Length) - { - if (thisMarker >= s1.Length) - { - break; - } - char thisCh = s1[thisMarker]; - - StringBuilder thisChunk = new StringBuilder(); - - while ((thisMarker < s1.Length) && (thisChunk.Length == 0 || SortHelper.InChunk(thisCh, thisChunk[0]))) - { - thisChunk.Append(thisCh); - thisMarker++; - - if (thisMarker < s1.Length) - { - thisCh = s1[thisMarker]; - } - } - - var isNumeric = thisChunk.Length > 0 && char.IsDigit(thisChunk[0]); - list.Add(new Tuple<StringBuilder, bool>(thisChunk, isNumeric)); - } - - return list; - } - - /// <summary> - /// This is just a helper for convenience - /// </summary> - /// <value>The primary image path.</value> - [IgnoreDataMember] - public string PrimaryImagePath - { - get { return this.GetImagePath(ImageType.Primary); } - } - - public virtual bool IsInternetMetadataEnabled() - { - return LibraryManager.GetLibraryOptions(this).EnableInternetProviders; - } - - public virtual bool CanDelete() - { - if (SourceType == SourceType.Channel) - { - return false; - } - - var locationType = LocationType; - return locationType != LocationType.Remote && - locationType != LocationType.Virtual; - } - - public virtual bool IsAuthorizedToDelete(User user, List<Folder> allCollectionFolders) - { - 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) - { - var allCollectionFolders = LibraryManager.GetUserRootFolder().Children.OfType<Folder>().ToList(); - return CanDelete(user, allCollectionFolders); - } - - public virtual bool CanDownload() - { - return false; - } - - public virtual bool IsAuthorizedToDownload(User user) - { - return user.Policy.EnableContentDownloading; - } - - public bool CanDownload(User user) - { - return CanDownload() && IsAuthorizedToDownload(user); - } - - /// <summary> - /// Gets or sets the date created. - /// </summary> - /// <value>The date created.</value> - [IgnoreDataMember] - public DateTime DateCreated { get; set; } - - /// <summary> - /// Gets or sets the date modified. - /// </summary> - /// <value>The date modified.</value> - [IgnoreDataMember] - public DateTime DateModified { get; set; } - - [IgnoreDataMember] - public DateTime DateLastSaved { get; set; } - - [IgnoreDataMember] - public DateTime DateLastRefreshed { get; set; } - - [IgnoreDataMember] - public virtual bool EnableRefreshOnDateModifiedChange - { - get { return false; } - } - - /// <summary> - /// The logger - /// </summary> - public static ILogger Logger { get; set; } - public static ILibraryManager LibraryManager { get; set; } - public static IServerConfigurationManager ConfigurationManager { get; set; } - public static IProviderManager ProviderManager { get; set; } - public static ILocalizationManager LocalizationManager { get; set; } - public static IItemRepository ItemRepository { get; set; } - public static IFileSystem FileSystem { get; set; } - public static IUserDataManager UserDataManager { get; set; } - public static ILiveTvManager LiveTvManager { get; set; } - public static IChannelManager ChannelManager { get; set; } - public static ICollectionManager CollectionManager { get; set; } - public static IImageProcessor ImageProcessor { get; set; } - public static IMediaSourceManager MediaSourceManager { get; set; } - public static IMediaEncoder MediaEncoder { get; set; } - - /// <summary> - /// Returns a <see cref="System.String" /> that represents this instance. - /// </summary> - /// <returns>A <see cref="System.String" /> that represents this instance.</returns> - public override string ToString() - { - return Name; - } - - [IgnoreDataMember] - public bool IsLocked { get; set; } - - /// <summary> - /// Gets or sets the locked fields. - /// </summary> - /// <value>The locked fields.</value> - [IgnoreDataMember] - public MetadataFields[] LockedFields { get; set; } - - /// <summary> - /// Gets the type of the media. - /// </summary> - /// <value>The type of the media.</value> - [IgnoreDataMember] - public virtual string MediaType - { - get - { - return null; - } - } - - [IgnoreDataMember] - public virtual string[] PhysicalLocations - { - get - { - var locationType = LocationType; - - if (locationType == LocationType.Remote || locationType == LocationType.Virtual) - { - return new string[] { }; - } - - return new[] { Path }; - } - } - - private string _forcedSortName; - /// <summary> - /// Gets or sets the name of the forced sort. - /// </summary> - /// <value>The name of the forced sort.</value> - [IgnoreDataMember] - public string ForcedSortName - { - get { return _forcedSortName; } - set { _forcedSortName = value; _sortName = null; } - } - - private string _sortName; - /// <summary> - /// Gets the name of the sort. - /// </summary> - /// <value>The name of the sort.</value> - [IgnoreDataMember] - public string SortName - { - get - { - if (_sortName == null) - { - if (!string.IsNullOrWhiteSpace(ForcedSortName)) - { - // Need the ToLower because that's what CreateSortName does - _sortName = ModifySortChunks(ForcedSortName).ToLower(); - } - else - { - _sortName = CreateSortName(); - } - } - return _sortName; - } - set - { - _sortName = value; - } - } - - public string GetInternalMetadataPath() - { - var basePath = ConfigurationManager.ApplicationPaths.InternalMetadataPath; - - return GetInternalMetadataPath(basePath); - } - - protected virtual string GetInternalMetadataPath(string basePath) - { - if (SourceType == SourceType.Channel) - { - return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N")); - } - - var idString = Id.ToString("N"); - - basePath = System.IO.Path.Combine(basePath, "library"); - - return System.IO.Path.Combine(basePath, idString.Substring(0, 2), idString); - } - - /// <summary> - /// Creates the name of the sort. - /// </summary> - /// <returns>System.String.</returns> - protected virtual string CreateSortName() - { - if (Name == null) return null; //some items may not have name filled in properly - - if (!EnableAlphaNumericSorting) - { - return Name.TrimStart(); - } - - var sortable = Name.Trim().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) - { - // Remove from beginning if a space follows - if (sortable.StartsWith(search + " ")) - { - sortable = sortable.Remove(0, search.Length + 1); - } - // Remove from middle if surrounded by spaces - sortable = sortable.Replace(" " + search + " ", " "); - - // Remove from end if followed by a space - if (sortable.EndsWith(" " + search)) - { - sortable = sortable.Remove(sortable.Length - (search.Length + 1)); - } - } - - return ModifySortChunks(sortable); - } - - private string ModifySortChunks(string name) - { - var chunks = GetSortChunks(name); - - var builder = new StringBuilder(); - - foreach (var chunk in chunks) - { - var chunkBuilder = chunk.Item1; - - // This chunk is numeric - if (chunk.Item2) - { - while (chunkBuilder.Length < 10) - { - chunkBuilder.Insert(0, '0'); - } - } - - builder.Append(chunkBuilder); - } - //Logger.Debug("ModifySortChunks Start: {0} End: {1}", name, builder.ToString()); - return builder.ToString().RemoveDiacritics(); - } - - [IgnoreDataMember] - public Guid ParentId { get; set; } - - /// <summary> - /// Gets or sets the parent. - /// </summary> - /// <value>The parent.</value> - [IgnoreDataMember] - public Folder Parent - { - get { return GetParent() as Folder; } - set - { - - } - } - - public void SetParent(Folder parent) - { - ParentId = parent == null ? Guid.Empty : parent.Id; - } - - public BaseItem GetParent() - { - var parentId = ParentId; - if (parentId != Guid.Empty) - { - return LibraryManager.GetItemById(parentId); - } - - return null; - } - - public IEnumerable<BaseItem> GetParents() - { - var parent = GetParent(); - - while (parent != null) - { - yield return parent; - - parent = parent.GetParent(); - } - } - - /// <summary> - /// Finds a parent of a given type - /// </summary> - /// <typeparam name="T"></typeparam> - /// <returns>``0.</returns> - public T FindParent<T>() - where T : Folder - { - foreach (var parent in GetParents()) - { - var item = parent as T; - if (item != null) - { - return item; - } - } - return null; - } - - [IgnoreDataMember] - public virtual Guid? DisplayParentId - { - get - { - var parentId = ParentId; - - if (parentId == Guid.Empty) - { - return null; - } - return parentId; - } - } - - [IgnoreDataMember] - public BaseItem DisplayParent - { - get - { - var id = DisplayParentId; - if (!id.HasValue || id.Value == Guid.Empty) - { - return null; - } - return LibraryManager.GetItemById(id.Value); - } - } - - /// <summary> - /// When the item first debuted. For movies this could be premiere date, episodes would be first aired - /// </summary> - /// <value>The premiere date.</value> - [IgnoreDataMember] - public DateTime? PremiereDate { get; set; } - - /// <summary> - /// Gets or sets the end date. - /// </summary> - /// <value>The end date.</value> - [IgnoreDataMember] - public DateTime? EndDate { get; set; } - - /// <summary> - /// Gets or sets the official rating. - /// </summary> - /// <value>The official rating.</value> - [IgnoreDataMember] - public string OfficialRating { get; set; } - - [IgnoreDataMember] - public int InheritedParentalRatingValue { get; set; } - - /// <summary> - /// Gets or sets the critic rating. - /// </summary> - /// <value>The critic rating.</value> - [IgnoreDataMember] - public float? CriticRating { get; set; } - - /// <summary> - /// Gets or sets the custom rating. - /// </summary> - /// <value>The custom rating.</value> - [IgnoreDataMember] - public string CustomRating { get; set; } - - /// <summary> - /// Gets or sets the overview. - /// </summary> - /// <value>The overview.</value> - [IgnoreDataMember] - public string Overview { get; set; } - - /// <summary> - /// Gets or sets the studios. - /// </summary> - /// <value>The studios.</value> - [IgnoreDataMember] - public string[] Studios { get; set; } - - /// <summary> - /// Gets or sets the genres. - /// </summary> - /// <value>The genres.</value> - [IgnoreDataMember] - public List<string> Genres { get; set; } - - /// <summary> - /// Gets or sets the tags. - /// </summary> - /// <value>The tags.</value> - [IgnoreDataMember] - public string[] Tags { get; set; } - - [IgnoreDataMember] - public string[] ProductionLocations { get; set; } - - /// <summary> - /// Gets or sets the home page URL. - /// </summary> - /// <value>The home page URL.</value> - [IgnoreDataMember] - public string HomePageUrl { get; set; } - - /// <summary> - /// Gets or sets the community rating. - /// </summary> - /// <value>The community rating.</value> - [IgnoreDataMember] - public float? CommunityRating { get; set; } - - /// <summary> - /// Gets or sets the run time ticks. - /// </summary> - /// <value>The run time ticks.</value> - [IgnoreDataMember] - public long? RunTimeTicks { get; set; } - - /// <summary> - /// Gets or sets the production year. - /// </summary> - /// <value>The production year.</value> - [IgnoreDataMember] - public int? ProductionYear { get; set; } - - /// <summary> - /// If the item is part of a series, this is it's number in the series. - /// This could be episode number, album track number, etc. - /// </summary> - /// <value>The index number.</value> - [IgnoreDataMember] - public int? IndexNumber { get; set; } - - /// <summary> - /// For an episode this could be the season number, or for a song this could be the disc number. - /// </summary> - /// <value>The parent index number.</value> - [IgnoreDataMember] - public int? ParentIndexNumber { get; set; } - - [IgnoreDataMember] - public string OfficialRatingForComparison - { - get - { - var officialRating = OfficialRating; - if (!string.IsNullOrWhiteSpace(officialRating)) - { - return officialRating; - } - - var parent = DisplayParent; - if (parent != null) - { - return parent.OfficialRatingForComparison; - } - - return null; - } - } - - [IgnoreDataMember] - public string CustomRatingForComparison - { - get - { - var customRating = CustomRating; - if (!string.IsNullOrWhiteSpace(customRating)) - { - return customRating; - } - - var parent = DisplayParent; - if (parent != null) - { - return parent.CustomRatingForComparison; - } - - return null; - } - } - - /// <summary> - /// Gets the play access. - /// </summary> - /// <param name="user">The user.</param> - /// <returns>PlayAccess.</returns> - public PlayAccess GetPlayAccess(User user) - { - if (!user.Policy.EnableMediaPlayback) - { - return PlayAccess.None; - } - - //if (!user.IsParentalScheduleAllowed()) - //{ - // return PlayAccess.None; - //} - - return PlayAccess.Full; - } - - /// <summary> - /// Loads the theme songs. - /// </summary> - /// <returns>List{Audio.Audio}.</returns> - private static Audio.Audio[] LoadThemeSongs(List<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService) - { - var files = fileSystemChildren.Where(i => i.IsDirectory) - .Where(i => string.Equals(i.Name, ThemeSongsFolderName, StringComparison.OrdinalIgnoreCase)) - .SelectMany(i => FileSystem.GetFiles(i.FullName)) - .ToList(); - - // Support plex/xbmc convention - files.AddRange(fileSystemChildren - .Where(i => !i.IsDirectory && string.Equals(FileSystem.GetFileNameWithoutExtension(i), ThemeSongFilename, StringComparison.OrdinalIgnoreCase)) - ); - - return LibraryManager.ResolvePaths(files, directoryService, null, new LibraryOptions()) - .OfType<Audio.Audio>() - .Select(audio => - { - // Try to retrieve it from the db. If we don't find it, use the resolved version - var dbItem = LibraryManager.GetItemById(audio.Id) as Audio.Audio; - - if (dbItem != null) - { - audio = dbItem; - } - else - { - // item is new - audio.ExtraType = MediaBrowser.Model.Entities.ExtraType.ThemeSong; - } - - return audio; - - // Sort them so that the list can be easily compared for changes - }).OrderBy(i => i.Path).ToArray(); - } - - /// <summary> - /// Loads the video backdrops. - /// </summary> - /// <returns>List{Video}.</returns> - private static Video[] LoadThemeVideos(IEnumerable<FileSystemMetadata> fileSystemChildren, IDirectoryService directoryService) - { - var files = fileSystemChildren.Where(i => i.IsDirectory) - .Where(i => string.Equals(i.Name, ThemeVideosFolderName, StringComparison.OrdinalIgnoreCase)) - .SelectMany(i => FileSystem.GetFiles(i.FullName)); - - return LibraryManager.ResolvePaths(files, directoryService, null, new LibraryOptions()) - .OfType<Video>() - .Select(item => - { - // Try to retrieve it from the db. If we don't find it, use the resolved version - var dbItem = LibraryManager.GetItemById(item.Id) as Video; - - if (dbItem != null) - { - item = dbItem; - } - else - { - // item is new - item.ExtraType = MediaBrowser.Model.Entities.ExtraType.ThemeVideo; - } - - return item; - - // Sort them so that the list can be easily compared for changes - }).OrderBy(i => i.Path).ToArray(); - } - - public Task RefreshMetadata(CancellationToken cancellationToken) - { - return RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(Logger, FileSystem)), cancellationToken); - } - - protected virtual void TriggerOnRefreshStart() - { - - } - - protected virtual void TriggerOnRefreshComplete() - { - - } - - /// <summary> - /// Overrides the base implementation to refresh metadata for local trailers - /// </summary> - /// <param name="options">The options.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>true if a provider reports we changed</returns> - public async Task<ItemUpdateType> RefreshMetadata(MetadataRefreshOptions options, CancellationToken cancellationToken) - { - TriggerOnRefreshStart(); - - var locationType = LocationType; - - var requiresSave = false; - - if (SupportsOwnedItems) - { - try - { - var files = locationType != LocationType.Remote && locationType != LocationType.Virtual ? - GetFileSystemChildren(options.DirectoryService).ToList() : - new List<FileSystemMetadata>(); - - var ownedItemsChanged = await RefreshedOwnedItems(options, files, cancellationToken).ConfigureAwait(false); - - if (ownedItemsChanged) - { - requiresSave = true; - } - } - catch (Exception ex) - { - Logger.ErrorException("Error refreshing owned items for {0}", ex, Path ?? Name); - } - } - - try - { - var refreshOptions = requiresSave - ? new MetadataRefreshOptions(options) - { - ForceSave = true - } - : options; - - return await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false); - } - finally - { - TriggerOnRefreshComplete(); - } - } - - [IgnoreDataMember] - protected virtual bool SupportsOwnedItems - { - get { return IsFolder || GetParent() != null; } - } - - [IgnoreDataMember] - public virtual bool SupportsPeople - { - get { return false; } - } - - [IgnoreDataMember] - public virtual bool SupportsThemeMedia - { - get { return false; } - } - - /// <summary> - /// Refreshes owned items such as trailers, theme videos, special features, etc. - /// Returns true or false indicating if changes were found. - /// </summary> - /// <param name="options"></param> - /// <param name="fileSystemChildren"></param> - /// <param name="cancellationToken"></param> - /// <returns></returns> - protected virtual async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) - { - var themeSongsChanged = false; - - var themeVideosChanged = false; - - var localTrailersChanged = false; - - if (LocationType == LocationType.FileSystem && GetParent() != null) - { - if (SupportsThemeMedia) - { - if (!IsInMixedFolder) - { - themeSongsChanged = await RefreshThemeSongs(this, options, fileSystemChildren, cancellationToken).ConfigureAwait(false); - - themeVideosChanged = await RefreshThemeVideos(this, options, fileSystemChildren, cancellationToken).ConfigureAwait(false); - } - } - - var hasTrailers = this as IHasTrailers; - if (hasTrailers != null) - { - localTrailersChanged = await RefreshLocalTrailers(hasTrailers, options, fileSystemChildren, cancellationToken).ConfigureAwait(false); - } - } - - return themeSongsChanged || themeVideosChanged || localTrailersChanged; - } - - protected virtual FileSystemMetadata[] GetFileSystemChildren(IDirectoryService directoryService) - { - var path = ContainingFolderPath; - - return directoryService.GetFileSystemEntries(path); - } - - private async Task<bool> RefreshLocalTrailers(IHasTrailers item, MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) - { - var newItems = LibraryManager.FindTrailers(this, fileSystemChildren, options.DirectoryService).ToList(); - - var newItemIds = newItems.Select(i => i.Id).ToArray(); - - var itemsChanged = !item.LocalTrailerIds.SequenceEqual(newItemIds); - var ownerId = item.Id; - - 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); - - item.LocalTrailerIds = newItemIds; - - return itemsChanged; - } - - private async Task<bool> RefreshThemeVideos(BaseItem item, MetadataRefreshOptions options, IEnumerable<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) - { - var newThemeVideos = LoadThemeVideos(fileSystemChildren, options.DirectoryService); - - var newThemeVideoIds = newThemeVideos.Select(i => i.Id).ToArray(newThemeVideos.Length); - - var themeVideosChanged = !item.ThemeVideoIds.SequenceEqual(newThemeVideoIds); - - var ownerId = item.Id; - - var tasks = newThemeVideos.Select(i => - { - var subOptions = new MetadataRefreshOptions(options); - - if (!i.ExtraType.HasValue || - i.ExtraType.Value != Model.Entities.ExtraType.ThemeVideo || - i.OwnerId != ownerId || - i.ParentId != Guid.Empty) - { - i.ExtraType = Model.Entities.ExtraType.ThemeVideo; - i.OwnerId = ownerId; - i.ParentId = Guid.Empty; - subOptions.ForceSave = true; - } - - return RefreshMetadataForOwnedItem(i, true, subOptions, cancellationToken); - }); - - await Task.WhenAll(tasks).ConfigureAwait(false); - - item.ThemeVideoIds = newThemeVideoIds; - - return themeVideosChanged; - } - - /// <summary> - /// Refreshes the theme songs. - /// </summary> - private async Task<bool> RefreshThemeSongs(BaseItem item, MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) - { - var newThemeSongs = LoadThemeSongs(fileSystemChildren, options.DirectoryService); - var newThemeSongIds = newThemeSongs.Select(i => i.Id).ToArray(newThemeSongs.Length); - - var themeSongsChanged = !item.ThemeSongIds.SequenceEqual(newThemeSongIds); - - var ownerId = item.Id; - - var tasks = newThemeSongs.Select(i => - { - var subOptions = new MetadataRefreshOptions(options); - - if (!i.ExtraType.HasValue || - i.ExtraType.Value != Model.Entities.ExtraType.ThemeSong || - i.OwnerId != ownerId || - i.ParentId != Guid.Empty) - { - i.ExtraType = Model.Entities.ExtraType.ThemeSong; - i.OwnerId = ownerId; - i.ParentId = Guid.Empty; - subOptions.ForceSave = true; - } - - return RefreshMetadataForOwnedItem(i, true, subOptions, cancellationToken); - }); - - await Task.WhenAll(tasks).ConfigureAwait(false); - - item.ThemeSongIds = newThemeSongIds; - - return themeSongsChanged; - } - - /// <summary> - /// Gets or sets the provider ids. - /// </summary> - /// <value>The provider ids.</value> - [IgnoreDataMember] - public Dictionary<string, string> ProviderIds { get; set; } - - [IgnoreDataMember] - public virtual Folder LatestItemsIndexContainer - { - get { return null; } - } - - public virtual double? GetDefaultPrimaryImageAspectRatio() - { - return null; - } - - public virtual string CreatePresentationUniqueKey() - { - return Id.ToString("N"); - } - - [IgnoreDataMember] - public string PresentationUniqueKey { get; set; } - - public string GetPresentationUniqueKey() - { - return PresentationUniqueKey ?? CreatePresentationUniqueKey(); - } - - public virtual bool RequiresRefresh() - { - return false; - } - - public virtual List<string> GetUserDataKeys() - { - var list = new List<string>(); - - if (SourceType == SourceType.Channel) - { - if (!string.IsNullOrWhiteSpace(ExternalId)) - { - list.Add(ExternalId); - } - } - - list.Add(Id.ToString()); - return list; - } - - internal virtual ItemUpdateType UpdateFromResolvedItem(BaseItem newItem) - { - var updateType = ItemUpdateType.None; - - if (IsInMixedFolder != newItem.IsInMixedFolder) - { - IsInMixedFolder = newItem.IsInMixedFolder; - updateType |= ItemUpdateType.MetadataImport; - } - - return updateType; - } - - public void AfterMetadataRefresh() - { - _sortName = null; - } - - /// <summary> - /// Gets the preferred metadata language. - /// </summary> - /// <returns>System.String.</returns> - public string GetPreferredMetadataLanguage() - { - string lang = PreferredMetadataLanguage; - - if (string.IsNullOrWhiteSpace(lang)) - { - lang = GetParents() - .Select(i => i.PreferredMetadataLanguage) - .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); - } - - if (string.IsNullOrWhiteSpace(lang)) - { - lang = LibraryManager.GetCollectionFolders(this) - .Select(i => i.PreferredMetadataLanguage) - .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); - } - - if (string.IsNullOrWhiteSpace(lang)) - { - lang = LibraryManager.GetLibraryOptions(this).PreferredMetadataLanguage; - } - - if (string.IsNullOrWhiteSpace(lang)) - { - lang = ConfigurationManager.Configuration.PreferredMetadataLanguage; - } - - return lang; - } - - /// <summary> - /// Gets the preferred metadata language. - /// </summary> - /// <returns>System.String.</returns> - public string GetPreferredMetadataCountryCode() - { - string lang = PreferredMetadataCountryCode; - - if (string.IsNullOrWhiteSpace(lang)) - { - lang = GetParents() - .Select(i => i.PreferredMetadataCountryCode) - .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); - } - - if (string.IsNullOrWhiteSpace(lang)) - { - lang = LibraryManager.GetCollectionFolders(this) - .Select(i => i.PreferredMetadataCountryCode) - .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i)); - } - - if (string.IsNullOrWhiteSpace(lang)) - { - lang = LibraryManager.GetLibraryOptions(this).MetadataCountryCode; - } - - if (string.IsNullOrWhiteSpace(lang)) - { - lang = ConfigurationManager.Configuration.MetadataCountryCode; - } - - return lang; - } - - public virtual bool IsSaveLocalMetadataEnabled() - { - if (SourceType == SourceType.Channel) - { - return false; - } - - var libraryOptions = LibraryManager.GetLibraryOptions(this); - - return libraryOptions.SaveLocalMetadata; - } - - /// <summary> - /// Determines if a given user has access to this item - /// </summary> - /// <param name="user">The user.</param> - /// <returns><c>true</c> if [is parental allowed] [the specified user]; otherwise, <c>false</c>.</returns> - /// <exception cref="System.ArgumentNullException">user</exception> - public bool IsParentalAllowed(User user) - { - if (user == null) - { - throw new ArgumentNullException("user"); - } - - if (!IsVisibleViaTags(user)) - { - return false; - } - - var maxAllowedRating = user.Policy.MaxParentalRating; - - if (maxAllowedRating == null) - { - return true; - } - - var rating = CustomRatingForComparison; - - if (string.IsNullOrWhiteSpace(rating)) - { - rating = OfficialRatingForComparison; - } - - if (string.IsNullOrWhiteSpace(rating)) - { - return !GetBlockUnratedValue(user.Policy); - } - - var value = LocalizationManager.GetRatingLevel(rating); - - // Could not determine the integer value - if (!value.HasValue) - { - var isAllowed = !GetBlockUnratedValue(user.Policy); - - if (!isAllowed) - { - Logger.Debug("{0} has an unrecognized parental rating of {1}.", Name, rating); - } - - return isAllowed; - } - - return value.Value <= maxAllowedRating.Value; - } - - public int? GetParentalRatingValue() - { - var rating = CustomRating; - - if (string.IsNullOrWhiteSpace(rating)) - { - rating = OfficialRating; - } - - if (string.IsNullOrWhiteSpace(rating)) - { - return null; - } - - return LocalizationManager.GetRatingLevel(rating); - } - - public int? GetInheritedParentalRatingValue() - { - var rating = CustomRatingForComparison; - - if (string.IsNullOrWhiteSpace(rating)) - { - rating = OfficialRatingForComparison; - } - - if (string.IsNullOrWhiteSpace(rating)) - { - return null; - } - - return LocalizationManager.GetRatingLevel(rating); - } - - public List<string> GetInheritedTags() - { - var list = new List<string>(); - list.AddRange(Tags); - - foreach (var parent in GetParents()) - { - list.AddRange(parent.Tags); - } - - return list.Distinct(StringComparer.OrdinalIgnoreCase).ToList(); - } - - private bool IsVisibleViaTags(User user) - { - var policy = user.Policy; - if (policy.BlockedTags.Any(i => Tags.Contains(i, StringComparer.OrdinalIgnoreCase))) - { - return false; - } - - return true; - } - - protected virtual bool IsAllowTagFilterEnforced() - { - return true; - } - - public virtual UnratedItem GetBlockUnratedType() - { - if (SourceType == SourceType.Channel) - { - return UnratedItem.ChannelContent; - } - - return UnratedItem.Other; - } - - /// <summary> - /// Gets the block unrated value. - /// </summary> - /// <param name="config">The configuration.</param> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> - protected virtual bool GetBlockUnratedValue(UserPolicy config) - { - // Don't block plain folders that are unrated. Let the media underneath get blocked - // Special folders like series and albums will override this method. - if (IsFolder) - { - return false; - } - if (this is IItemByName) - { - return false; - } - - return config.BlockUnratedItems.Contains(GetBlockUnratedType()); - } - - /// <summary> - /// Determines if this folder should be visible to a given user. - /// Default is just parental allowed. Can be overridden for more functionality. - /// </summary> - /// <param name="user">The user.</param> - /// <returns><c>true</c> if the specified user is visible; otherwise, <c>false</c>.</returns> - /// <exception cref="System.ArgumentNullException">user</exception> - public virtual bool IsVisible(User user) - { - if (user == null) - { - throw new ArgumentNullException("user"); - } - - return IsParentalAllowed(user); - } - - public virtual bool IsVisibleStandalone(User user) - { - if (SourceType == SourceType.Channel) - { - return IsVisibleStandaloneInternal(user, false) && Channel.IsChannelVisible(this, user); - } - - return IsVisibleStandaloneInternal(user, true); - } - - [IgnoreDataMember] - public virtual bool SupportsInheritedParentImages - { - get { return false; } - } - - protected bool IsVisibleStandaloneInternal(User user, bool checkFolders) - { - if (!IsVisible(user)) - { - return false; - } - - if (GetParents().Any(i => !i.IsVisible(user))) - { - return false; - } - - if (checkFolders) - { - var topParent = GetParents().LastOrDefault() ?? this; - - if (string.IsNullOrWhiteSpace(topParent.Path)) - { - return true; - } - - var itemCollectionFolders = LibraryManager.GetCollectionFolders(this).Select(i => i.Id).ToList(); - - if (itemCollectionFolders.Count > 0) - { - var userCollectionFolders = user.RootFolder.GetChildren(user, true).Select(i => i.Id).ToList(); - if (!itemCollectionFolders.Any(userCollectionFolders.Contains)) - { - return false; - } - } - } - - return true; - } - - /// <summary> - /// Gets a value indicating whether this instance is folder. - /// </summary> - /// <value><c>true</c> if this instance is folder; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public virtual bool IsFolder - { - get - { - return false; - } - } - - [IgnoreDataMember] - public virtual bool IsDisplayedAsFolder - { - get - { - return false; - } - } - - public virtual string GetClientTypeName() - { - if (IsFolder && SourceType == SourceType.Channel && !(this is Channel)) - { - return "ChannelFolderItem"; - } - - return GetType().Name; - } - - /// <summary> - /// Gets the linked child. - /// </summary> - /// <param name="info">The info.</param> - /// <returns>BaseItem.</returns> - protected BaseItem GetLinkedChild(LinkedChild info) - { - // First get using the cached Id - if (info.ItemId.HasValue) - { - if (info.ItemId.Value == Guid.Empty) - { - return null; - } - - var itemById = LibraryManager.GetItemById(info.ItemId.Value); - - if (itemById != null) - { - return itemById; - } - } - - var item = FindLinkedChild(info); - - // If still null, log - if (item == null) - { - // Don't keep searching over and over - info.ItemId = Guid.Empty; - } - else - { - // Cache the id for next time - info.ItemId = item.Id; - } - - return item; - } - - private BaseItem FindLinkedChild(LinkedChild info) - { - if (!string.IsNullOrWhiteSpace(info.Path)) - { - var itemByPath = LibraryManager.FindByPath(info.Path, null); - - if (itemByPath == null) - { - //Logger.Warn("Unable to find linked item at path {0}", info.Path); - } - - return itemByPath; - } - - return null; - } - - [IgnoreDataMember] - public virtual bool EnableRememberingTrackSelections - { - get - { - return true; - } - } - - /// <summary> - /// Adds a studio to the item - /// </summary> - /// <param name="name">The name.</param> - /// <exception cref="System.ArgumentNullException"></exception> - public void AddStudio(string name) - { - if (string.IsNullOrWhiteSpace(name)) - { - throw new ArgumentNullException("name"); - } - - var current = Studios; - - if (!current.Contains(name, StringComparer.OrdinalIgnoreCase)) - { - if (current.Length == 0) - { - Studios = new[] { name }; - } - else - { - var list = current.ToArray(current.Length + 1); - list[list.Length - 1] = name; - Studios = list; - } - } - } - - public void SetStudios(IEnumerable<string> names) - { - Studios = names.Distinct().ToArray(); - } - - /// <summary> - /// Adds a genre to the item - /// </summary> - /// <param name="name">The name.</param> - /// <exception cref="System.ArgumentNullException"></exception> - public void AddGenre(string name) - { - if (string.IsNullOrWhiteSpace(name)) - { - throw new ArgumentNullException("name"); - } - - if (!Genres.Contains(name, StringComparer.OrdinalIgnoreCase)) - { - Genres.Add(name); - } - } - - /// <summary> - /// Marks the played. - /// </summary> - /// <param name="user">The user.</param> - /// <param name="datePlayed">The date played.</param> - /// <param name="resetPosition">if set to <c>true</c> [reset position].</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException"></exception> - public virtual void MarkPlayed(User user, - DateTime? datePlayed, - bool resetPosition) - { - if (user == null) - { - throw new ArgumentNullException(); - } - - var data = UserDataManager.GetUserData(user, this); - - if (datePlayed.HasValue) - { - // Increment - data.PlayCount++; - } - - // Ensure it's at least one - data.PlayCount = Math.Max(data.PlayCount, 1); - - if (resetPosition) - { - data.PlaybackPositionTicks = 0; - } - - data.LastPlayedDate = datePlayed ?? data.LastPlayedDate ?? DateTime.UtcNow; - data.Played = true; - - UserDataManager.SaveUserData(user.Id, this, data, UserDataSaveReason.TogglePlayed, CancellationToken.None); - } - - /// <summary> - /// Marks the unplayed. - /// </summary> - /// <param name="user">The user.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException"></exception> - public virtual void MarkUnplayed(User user) - { - if (user == null) - { - throw new ArgumentNullException(); - } - - var data = UserDataManager.GetUserData(user, this); - - //I think it is okay to do this here. - // if this is only called when a user is manually forcing something to un-played - // then it probably is what we want to do... - data.PlayCount = 0; - data.PlaybackPositionTicks = 0; - data.LastPlayedDate = null; - data.Played = false; - - UserDataManager.SaveUserData(user.Id, this, data, UserDataSaveReason.TogglePlayed, CancellationToken.None); - } - - /// <summary> - /// Do whatever refreshing is necessary when the filesystem pertaining to this item has changed. - /// </summary> - /// <returns>Task.</returns> - public virtual void ChangedExternally() - { - ProviderManager.QueueRefresh(Id, new MetadataRefreshOptions(FileSystem) - { - ValidateChildren = true, - - }, RefreshPriority.High); - } - - /// <summary> - /// Gets an image - /// </summary> - /// <param name="type">The type.</param> - /// <param name="imageIndex">Index of the image.</param> - /// <returns><c>true</c> if the specified type has image; otherwise, <c>false</c>.</returns> - /// <exception cref="System.ArgumentException">Backdrops should be accessed using Item.Backdrops</exception> - public bool HasImage(ImageType type, int imageIndex) - { - return GetImageInfo(type, imageIndex) != null; - } - - public void SetImage(ItemImageInfo image, int index) - { - if (image.Type == ImageType.Chapter) - { - throw new ArgumentException("Cannot set chapter images using SetImagePath"); - } - - var existingImage = GetImageInfo(image.Type, index); - - if (existingImage != null) - { - existingImage.Path = image.Path; - existingImage.DateModified = image.DateModified; - existingImage.Width = image.Width; - existingImage.Height = image.Height; - } - - else - { - var currentCount = ImageInfos.Length; - var newList = ImageInfos.ToArray(currentCount + 1); - newList[currentCount] = image; - ImageInfos = newList; - } - } - - public void SetImagePath(ImageType type, int index, FileSystemMetadata file) - { - if (type == ImageType.Chapter) - { - throw new ArgumentException("Cannot set chapter images using SetImagePath"); - } - - var image = GetImageInfo(type, index); - - if (image == null) - { - var currentCount = ImageInfos.Length; - var newList = ImageInfos.ToArray(currentCount + 1); - newList[currentCount] = GetImageInfo(file, type); - ImageInfos = newList; - } - else - { - var imageInfo = GetImageInfo(file, type); - - image.Path = file.FullName; - image.DateModified = imageInfo.DateModified; - - // reset these values - image.Width = 0; - image.Height = 0; - } - } - - /// <summary> - /// Deletes the image. - /// </summary> - /// <param name="type">The type.</param> - /// <param name="index">The index.</param> - /// <returns>Task.</returns> - public void DeleteImage(ImageType type, int index) - { - var info = GetImageInfo(type, index); - - if (info == null) - { - // Nothing to do - return; - } - - // Remove it from the item - RemoveImage(info); - - if (info.IsLocalFile) - { - FileSystem.DeleteFile(info.Path); - } - - UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); - } - - public void RemoveImage(ItemImageInfo image) - { - RemoveImages(new List<ItemImageInfo> { image }); - } - - public void RemoveImages(List<ItemImageInfo> deletedImages) - { - ImageInfos = ImageInfos.Except(deletedImages).ToArray(); - } - - public virtual void UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken) - { - LibraryManager.UpdateItem(this, updateReason, cancellationToken); - } - - /// <summary> - /// Validates that images within the item are still on the file system - /// </summary> - public bool ValidateImages(IDirectoryService directoryService) - { - var allFiles = ImageInfos - .Where(i => i.IsLocalFile) - .Select(i => FileSystem.GetDirectoryName(i.Path)) - .Distinct(StringComparer.OrdinalIgnoreCase) - .SelectMany(i => directoryService.GetFilePaths(i)) - .ToList(); - - var deletedImages = ImageInfos - .Where(image => image.IsLocalFile && !allFiles.Contains(image.Path, StringComparer.OrdinalIgnoreCase)) - .ToList(); - - if (deletedImages.Count > 0) - { - ImageInfos = ImageInfos.Except(deletedImages).ToArray(); - } - - return deletedImages.Count > 0; - } - - /// <summary> - /// Gets the image path. - /// </summary> - /// <param name="imageType">Type of the image.</param> - /// <param name="imageIndex">Index of the image.</param> - /// <returns>System.String.</returns> - /// <exception cref="System.InvalidOperationException"> - /// </exception> - /// <exception cref="System.ArgumentNullException">item</exception> - public string GetImagePath(ImageType imageType, int imageIndex) - { - var info = GetImageInfo(imageType, imageIndex); - - return info == null ? null : info.Path; - } - - /// <summary> - /// Gets the image information. - /// </summary> - /// <param name="imageType">Type of the image.</param> - /// <param name="imageIndex">Index of the image.</param> - /// <returns>ItemImageInfo.</returns> - public ItemImageInfo GetImageInfo(ImageType imageType, int imageIndex) - { - if (imageType == ImageType.Chapter) - { - var chapter = ItemRepository.GetChapter(Id, imageIndex); - - if (chapter == null) - { - return null; - } - - var path = chapter.ImagePath; - - if (string.IsNullOrWhiteSpace(path)) - { - return null; - } - - return new ItemImageInfo - { - Path = path, - DateModified = chapter.ImageDateModified, - Type = imageType - }; - } - - return GetImages(imageType) - .ElementAtOrDefault(imageIndex); - } - - public IEnumerable<ItemImageInfo> GetImages(ImageType imageType) - { - if (imageType == ImageType.Chapter) - { - throw new ArgumentException("No image info for chapter images"); - } - - return ImageInfos.Where(i => i.Type == imageType); - } - - /// <summary> - /// Adds the images. - /// </summary> - /// <param name="imageType">Type of the image.</param> - /// <param name="images">The images.</param> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> - /// <exception cref="System.ArgumentException">Cannot call AddImages with chapter images</exception> - public bool AddImages(ImageType imageType, List<FileSystemMetadata> images) - { - if (imageType == ImageType.Chapter) - { - throw new ArgumentException("Cannot call AddImages with chapter images"); - } - - var existingImages = GetImages(imageType) - .ToList(); - - var newImageList = new List<FileSystemMetadata>(); - var imageAdded = false; - var imageUpdated = false; - - foreach (var newImage in images) - { - if (newImage == null) - { - throw new ArgumentException("null image found in list"); - } - - var existing = existingImages - .FirstOrDefault(i => string.Equals(i.Path, newImage.FullName, StringComparison.OrdinalIgnoreCase)); - - if (existing == null) - { - newImageList.Add(newImage); - imageAdded = true; - } - else - { - if (existing.IsLocalFile) - { - var newDateModified = FileSystem.GetLastWriteTimeUtc(newImage); - - // If date changed then we need to reset saved image dimensions - if (existing.DateModified != newDateModified && (existing.Width > 0 || existing.Height > 0)) - { - existing.Width = 0; - existing.Height = 0; - imageUpdated = true; - } - - existing.DateModified = newDateModified; - } - } - } - - if (imageAdded || images.Count != existingImages.Count) - { - var newImagePaths = images.Select(i => i.FullName).ToList(); - - var deleted = existingImages - .Where(i => i.IsLocalFile && !newImagePaths.Contains(i.Path, StringComparer.OrdinalIgnoreCase) && !FileSystem.FileExists(i.Path)) - .ToList(); - - if (deleted.Count > 0) - { - ImageInfos = ImageInfos.Except(deleted).ToArray(); - } - } - - if (newImageList.Count > 0) - { - var currentCount = ImageInfos.Length; - var newList = ImageInfos.ToArray(currentCount + newImageList.Count); - - foreach (var image in newImageList) - { - newList[currentCount] = GetImageInfo(image, imageType); - currentCount++; - } - - ImageInfos = newList; - } - - return imageUpdated || newImageList.Count > 0; - } - - private ItemImageInfo GetImageInfo(FileSystemMetadata file, ImageType type) - { - return new ItemImageInfo - { - Path = file.FullName, - Type = type, - DateModified = FileSystem.GetLastWriteTimeUtc(file) - }; - } - - /// <summary> - /// Gets the file system path to delete when the item is to be deleted - /// </summary> - /// <returns></returns> - public virtual IEnumerable<FileSystemMetadata> GetDeletePaths() - { - return new[] { - new FileSystemMetadata - { - FullName = Path, - IsDirectory = IsFolder - } - }.Concat(GetLocalMetadataFilesToDelete()); - } - - protected List<FileSystemMetadata> GetLocalMetadataFilesToDelete() - { - if (IsFolder || !IsInMixedFolder) - { - return new List<FileSystemMetadata>(); - } - - var filename = System.IO.Path.GetFileNameWithoutExtension(Path); - var extensions = new List<string> { ".nfo", ".xml", ".srt", ".vtt", ".sub", ".idx", ".txt", ".edl" }; - 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)) - .ToList(); - } - - public bool AllowsMultipleImages(ImageType type) - { - return type == ImageType.Backdrop || type == ImageType.Screenshot || type == ImageType.Chapter; - } - - public void SwapImages(ImageType type, int index1, int index2) - { - if (!AllowsMultipleImages(type)) - { - throw new ArgumentException("The change index operation is only applicable to backdrops and screenshots"); - } - - var info1 = GetImageInfo(type, index1); - var info2 = GetImageInfo(type, index2); - - if (info1 == null || info2 == null) - { - // Nothing to do - return; - } - - if (!info1.IsLocalFile || !info2.IsLocalFile) - { - // TODO: Not supported yet - return; - } - - var path1 = info1.Path; - var path2 = info2.Path; - - FileSystem.SwapFiles(path1, path2); - - // Refresh these values - info1.DateModified = FileSystem.GetLastWriteTimeUtc(info1.Path); - info2.DateModified = FileSystem.GetLastWriteTimeUtc(info2.Path); - - info1.Width = 0; - info1.Height = 0; - info2.Width = 0; - info2.Height = 0; - - UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); - } - - public virtual bool IsPlayed(User user) - { - var userdata = UserDataManager.GetUserData(user, this); - - return userdata != null && userdata.Played; - } - - public bool IsFavoriteOrLiked(User user) - { - var userdata = UserDataManager.GetUserData(user, this); - - return userdata != null && (userdata.IsFavorite || (userdata.Likes ?? false)); - } - - public virtual bool IsUnplayed(User user) - { - if (user == null) - { - throw new ArgumentNullException("user"); - } - - var userdata = UserDataManager.GetUserData(user, this); - - return userdata == null || !userdata.Played; - } - - ItemLookupInfo IHasLookupInfo<ItemLookupInfo>.GetLookupInfo() - { - return GetItemLookupInfo<ItemLookupInfo>(); - } - - protected T GetItemLookupInfo<T>() - where T : ItemLookupInfo, new() - { - return new T - { - MetadataCountryCode = GetPreferredMetadataCountryCode(), - MetadataLanguage = GetPreferredMetadataLanguage(), - Name = GetNameForMetadataLookup(), - ProviderIds = ProviderIds, - IndexNumber = IndexNumber, - ParentIndexNumber = ParentIndexNumber, - Year = ProductionYear, - PremiereDate = PremiereDate - }; - } - - protected virtual string GetNameForMetadataLookup() - { - return Name; - } - - /// <summary> - /// This is called before any metadata refresh and returns true or false indicating if changes were made - /// </summary> - public virtual bool BeforeMetadataRefresh() - { - _sortName = null; - - var hasChanges = false; - - if (string.IsNullOrEmpty(Name) && !string.IsNullOrEmpty(Path)) - { - Name = FileSystem.GetFileNameWithoutExtension(Path); - hasChanges = true; - } - - return hasChanges; - } - - protected static string GetMappedPath(BaseItem item, string path, LocationType locationType) - { - if (locationType == LocationType.FileSystem || locationType == LocationType.Offline) - { - return LibraryManager.GetPathAfterNetworkSubstitution(path, item); - } - - return path; - } - - public virtual void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user, ItemFields[] fields) - { - if (RunTimeTicks.HasValue) - { - double pct = RunTimeTicks.Value; - - if (pct > 0) - { - pct = userData.PlaybackPositionTicks / pct; - - if (pct > 0) - { - dto.PlayedPercentage = 100 * pct; - } - } - } - } - - protected Task RefreshMetadataForOwnedItem(BaseItem ownedItem, bool copyTitleMetadata, MetadataRefreshOptions options, CancellationToken cancellationToken) - { - var newOptions = new MetadataRefreshOptions(options); - newOptions.SearchResult = null; - - var item = this; - - if (copyTitleMetadata) - { - // Take some data from the main item, for querying purposes - if (!item.Genres.SequenceEqual(ownedItem.Genres, StringComparer.Ordinal)) - { - newOptions.ForceSave = true; - ownedItem.Genres = item.Genres.ToList(); - } - if (!item.Studios.SequenceEqual(ownedItem.Studios, StringComparer.Ordinal)) - { - newOptions.ForceSave = true; - ownedItem.Studios = item.Studios; - } - if (!item.ProductionLocations.SequenceEqual(ownedItem.ProductionLocations, StringComparer.Ordinal)) - { - newOptions.ForceSave = true; - ownedItem.ProductionLocations = item.ProductionLocations; - } - if (item.CommunityRating != ownedItem.CommunityRating) - { - ownedItem.CommunityRating = item.CommunityRating; - newOptions.ForceSave = true; - } - if (item.CriticRating != ownedItem.CriticRating) - { - ownedItem.CriticRating = item.CriticRating; - newOptions.ForceSave = true; - } - if (!string.Equals(item.Overview, ownedItem.Overview, StringComparison.Ordinal)) - { - ownedItem.Overview = item.Overview; - newOptions.ForceSave = true; - } - if (!string.Equals(item.OfficialRating, ownedItem.OfficialRating, StringComparison.Ordinal)) - { - ownedItem.OfficialRating = item.OfficialRating; - newOptions.ForceSave = true; - } - if (!string.Equals(item.CustomRating, ownedItem.CustomRating, StringComparison.Ordinal)) - { - ownedItem.CustomRating = item.CustomRating; - newOptions.ForceSave = true; - } - } - - return ownedItem.RefreshMetadata(newOptions, cancellationToken); - } - - protected Task RefreshMetadataForOwnedVideo(MetadataRefreshOptions options, bool copyTitleMetadata, string path, CancellationToken cancellationToken) - { - var newOptions = new MetadataRefreshOptions(options); - newOptions.SearchResult = null; - - var id = LibraryManager.GetNewItemId(path, typeof(Video)); - - // Try to retrieve it from the db. If we don't find it, use the resolved version - var video = LibraryManager.GetItemById(id) as Video; - - if (video == null) - { - video = LibraryManager.ResolvePath(FileSystem.GetFileSystemInfo(path)) as Video; - - 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); - } - - return RefreshMetadataForOwnedItem(video, copyTitleMetadata, newOptions, cancellationToken); - } - - public string GetEtag(User user) - { - var list = GetEtagValues(user); - - return string.Join("|", list.ToArray(list.Count)).GetMD5().ToString("N"); - } - - protected virtual List<string> GetEtagValues(User user) - { - return new List<string> - { - DateLastSaved.Ticks.ToString(CultureInfo.InvariantCulture) - }; - } - - public virtual IEnumerable<Guid> GetAncestorIds() - { - return GetParents().Select(i => i.Id).Concat(LibraryManager.GetCollectionFolders(this).Select(i => i.Id)); - } - - public BaseItem GetTopParent() - { - if (IsTopParent) - { - return this; - } - - foreach (var parent in GetParents()) - { - if (parent.IsTopParent) - { - return parent; - } - } - return null; - } - - [IgnoreDataMember] - public virtual bool IsTopParent - { - get - { - if (this is BasePluginFolder || this is Channel) - { - return true; - } - - var view = this as UserView; - if (view != null) - { - if (string.Equals(view.ViewType, CollectionType.LiveTv, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - if (string.Equals(view.ViewType, CollectionType.Channels, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - } - - if (GetParent() is AggregateFolder) - { - return true; - } - - return false; - } - } - - [IgnoreDataMember] - public virtual bool SupportsAncestors - { - get - { - return true; - } - } - - [IgnoreDataMember] - public virtual bool StopRefreshIfLocalMetadataFound - { - get - { - return true; - } - } - - public virtual IEnumerable<Guid> GetIdsForAncestorQuery() - { - return new[] { Id }; - } - - public virtual Task Delete(DeleteOptions options) - { - return LibraryManager.DeleteItem(this, options); - } - - public virtual List<ExternalUrl> GetRelatedUrls() - { - return new List<ExternalUrl>(); - } - - public virtual double? GetRefreshProgress() - { - 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/BasePluginFolder.cs b/MediaBrowser.Controller/Entities/BasePluginFolder.cs deleted file mode 100644 index c06f1cef4c..0000000000 --- a/MediaBrowser.Controller/Entities/BasePluginFolder.cs +++ /dev/null @@ -1,54 +0,0 @@ - -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Plugins derive from and export this class to create a folder that will appear in the root along - /// with all the other actual physical folders in the system. - /// </summary> - public abstract class BasePluginFolder : Folder, ICollectionFolder - { - [IgnoreDataMember] - public virtual string CollectionType - { - get { return null; } - } - - public override bool CanDelete() - { - return false; - } - - public override bool IsSaveLocalMetadataEnabled() - { - return true; - } - - [IgnoreDataMember] - public override bool SupportsInheritedParentImages - { - get - { - return false; - } - } - - [IgnoreDataMember] - public override bool SupportsPeople - { - get - { - return false; - } - } - - //public override double? GetDefaultPrimaryImageAspectRatio() - //{ - // double value = 16; - // value /= 9; - - // return value; - //} - } -} diff --git a/MediaBrowser.Controller/Entities/Book.cs b/MediaBrowser.Controller/Entities/Book.cs deleted file mode 100644 index 45e3915ce2..0000000000 --- a/MediaBrowser.Controller/Entities/Book.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System; -using System.Linq; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.Entities; - -namespace MediaBrowser.Controller.Entities -{ - public class Book : BaseItem, IHasLookupInfo<BookInfo>, IHasSeries - { - [IgnoreDataMember] - public override string MediaType - { - get - { - return Model.Entities.MediaType.Book; - } - } - - [IgnoreDataMember] - public string SeriesPresentationUniqueKey { get; set; } - [IgnoreDataMember] - public string SeriesName { get; set; } - [IgnoreDataMember] - public Guid? SeriesId { get; set; } - - public string FindSeriesSortName() - { - return SeriesName; - } - public string FindSeriesName() - { - return SeriesName; - } - public string FindSeriesPresentationUniqueKey() - { - return SeriesPresentationUniqueKey; - } - - public Guid? FindSeriesId() - { - return SeriesId; - } - - public override bool CanDownload() - { - var locationType = LocationType; - return locationType != LocationType.Remote && - locationType != LocationType.Virtual; - } - - public override UnratedItem GetBlockUnratedType() - { - return UnratedItem.Book; - } - - public BookInfo GetLookupInfo() - { - var info = GetItemLookupInfo<BookInfo>(); - - if (string.IsNullOrEmpty(SeriesName)) - { - info.SeriesName = GetParents().Select(i => i.Name).FirstOrDefault(); - } - else - { - info.SeriesName = SeriesName; - } - - return info; - } - } -} diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs deleted file mode 100644 index 03fca60c89..0000000000 --- a/MediaBrowser.Controller/Entities/CollectionFolder.cs +++ /dev/null @@ -1,387 +0,0 @@ -using MediaBrowser.Controller.IO; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Providers; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Specialized Folder class that points to a subset of the physical folders in the system. - /// It is created from the user-specific folders within the system root - /// </summary> - public class CollectionFolder : Folder, ICollectionFolder - { - public static IXmlSerializer XmlSerializer { get; set; } - - public CollectionFolder() - { - PhysicalLocationsList = EmptyStringArray; - PhysicalFolderIds = EmptyGuidArray; - } - - //public override double? GetDefaultPrimaryImageAspectRatio() - //{ - // double value = 16; - // value /= 9; - - // return value; - //} - - [IgnoreDataMember] - public override bool SupportsPlayedStatus - { - get - { - return false; - } - } - - [IgnoreDataMember] - public override bool SupportsInheritedParentImages - { - get - { - return false; - } - } - - public override bool CanDelete() - { - return false; - } - - public string CollectionType { get; set; } - - private static readonly Dictionary<string, LibraryOptions> LibraryOptions = new Dictionary<string, LibraryOptions>(); - public LibraryOptions GetLibraryOptions() - { - return GetLibraryOptions(Path); - } - - private static LibraryOptions LoadLibraryOptions(string path) - { - try - { - var result = XmlSerializer.DeserializeFromFile(typeof(LibraryOptions), GetLibraryOptionsPath(path)) as LibraryOptions; - - if (result == null) - { - return new LibraryOptions(); - } - - return result; - } - catch (FileNotFoundException) - { - return new LibraryOptions(); - } - catch (IOException) - { - return new LibraryOptions(); - } - catch (Exception ex) - { - Logger.ErrorException("Error loading library options", ex); - - return new LibraryOptions(); - } - } - - private static string GetLibraryOptionsPath(string path) - { - return System.IO.Path.Combine(path, "options.xml"); - } - - public void UpdateLibraryOptions(LibraryOptions options) - { - SaveLibraryOptions(Path, options); - } - - public static LibraryOptions GetLibraryOptions(string path) - { - lock (LibraryOptions) - { - LibraryOptions options; - if (!LibraryOptions.TryGetValue(path, out options)) - { - options = LoadLibraryOptions(path); - LibraryOptions[path] = options; - } - - return options; - } - } - - public static void SaveLibraryOptions(string path, LibraryOptions options) - { - lock (LibraryOptions) - { - LibraryOptions[path] = options; - - XmlSerializer.SerializeToFile(options, GetLibraryOptionsPath(path)); - } - } - - /// <summary> - /// Allow different display preferences for each collection folder - /// </summary> - /// <value>The display prefs id.</value> - [IgnoreDataMember] - public override Guid DisplayPreferencesId - { - get - { - return Id; - } - } - - [IgnoreDataMember] - public override string[] PhysicalLocations - { - get - { - return PhysicalLocationsList; - } - } - - public override bool IsSaveLocalMetadataEnabled() - { - return true; - } - - public string[] PhysicalLocationsList { get; set; } - public Guid[] PhysicalFolderIds { get; set; } - - protected override FileSystemMetadata[] GetFileSystemChildren(IDirectoryService directoryService) - { - return CreateResolveArgs(directoryService, true).FileSystemChildren; - } - - private bool _requiresRefresh; - public override bool RequiresRefresh() - { - var changed = base.RequiresRefresh() || _requiresRefresh; - - if (!changed) - { - var locations = PhysicalLocations; - - var newLocations = CreateResolveArgs(new DirectoryService(Logger, FileSystem), false).PhysicalLocations; - - if (!locations.SequenceEqual(newLocations)) - { - changed = true; - } - } - - if (!changed) - { - var folderIds = PhysicalFolderIds; - - var newFolderIds = GetPhysicalFolders(false).Select(i => i.Id).ToList(); - - if (!folderIds.SequenceEqual(newFolderIds)) - { - changed = true; - } - } - - return changed; - } - - public override bool BeforeMetadataRefresh() - { - var changed = base.BeforeMetadataRefresh() || _requiresRefresh; - _requiresRefresh = false; - return changed; - } - - public override double? GetRefreshProgress() - { - var folders = GetPhysicalFolders(true).ToList(); - double totalProgresses = 0; - var foldersWithProgress = 0; - - foreach (var folder in folders) - { - var progress = ProviderManager.GetRefreshProgress(folder.Id); - if (progress.HasValue) - { - totalProgresses += progress.Value; - foldersWithProgress++; - } - } - - if (foldersWithProgress == 0) - { - return null; - } - - return (totalProgresses / foldersWithProgress); - } - - protected override bool RefreshLinkedChildren(IEnumerable<FileSystemMetadata> fileSystemChildren) - { - return RefreshLinkedChildrenInternal(true); - } - - private bool RefreshLinkedChildrenInternal(bool setFolders) - { - var physicalFolders = GetPhysicalFolders(false) - .ToList(); - - var linkedChildren = physicalFolders - .SelectMany(c => c.LinkedChildren) - .ToList(); - - var changed = !linkedChildren.SequenceEqual(LinkedChildren, new LinkedChildComparer(FileSystem)); - - LinkedChildren = linkedChildren.ToArray(linkedChildren.Count); - - var folderIds = PhysicalFolderIds; - var newFolderIds = physicalFolders.Select(i => i.Id).ToArray(); - - if (!folderIds.SequenceEqual(newFolderIds)) - { - changed = true; - if (setFolders) - { - PhysicalFolderIds = newFolderIds; - } - } - - return changed; - } - - private ItemResolveArgs CreateResolveArgs(IDirectoryService directoryService, bool setPhysicalLocations) - { - var path = ContainingFolderPath; - - var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, directoryService) - { - FileInfo = FileSystem.GetDirectoryInfo(path), - Path = path, - Parent = GetParent() as Folder, - CollectionType = CollectionType - }; - - // Gather child folder and files - if (args.IsDirectory) - { - var isPhysicalRoot = args.IsPhysicalRoot; - - // When resolving the root, we need it's grandchildren (children of user views) - var flattenFolderDepth = isPhysicalRoot ? 2 : 0; - - var files = FileData.GetFilteredFileSystemEntries(directoryService, args.Path, FileSystem, Logger, args, flattenFolderDepth: flattenFolderDepth, resolveShortcuts: isPhysicalRoot || args.IsVf); - - // Need to remove subpaths that may have been resolved from shortcuts - // Example: if \\server\movies exists, then strip out \\server\movies\action - if (isPhysicalRoot) - { - files = LibraryManager.NormalizeRootPathList(files).ToArray(); - } - - args.FileSystemChildren = files; - } - - _requiresRefresh = _requiresRefresh || !args.PhysicalLocations.SequenceEqual(PhysicalLocations); - if (setPhysicalLocations) - { - PhysicalLocationsList = args.PhysicalLocations; - } - - return args; - } - - /// <summary> - /// Compare our current children (presumably just read from the repo) with the current state of the file system and adjust for any changes - /// ***Currently does not contain logic to maintain items that are unavailable in the file system*** - /// </summary> - /// <param name="progress">The progress.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="recursive">if set to <c>true</c> [recursive].</param> - /// <param name="refreshChildMetadata">if set to <c>true</c> [refresh child metadata].</param> - /// <param name="refreshOptions">The refresh options.</param> - /// <param name="directoryService">The directory service.</param> - /// <returns>Task.</returns> - protected override Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService) - { - return Task.FromResult(true); - } - - /// <summary> - /// Our children are actually just references to the ones in the physical root... - /// </summary> - /// <value>The actual children.</value> - [IgnoreDataMember] - public override IEnumerable<BaseItem> Children - { - get { return GetActualChildren(); } - } - - public IEnumerable<BaseItem> GetActualChildren() - { - return GetPhysicalFolders(true).SelectMany(c => c.Children); - } - - public IEnumerable<Folder> GetPhysicalFolders() - { - return GetPhysicalFolders(true); - } - - private IEnumerable<Folder> GetPhysicalFolders(bool enableCache) - { - if (enableCache) - { - return PhysicalFolderIds.Select(i => LibraryManager.GetItemById(i)).OfType<Folder>(); - } - - var rootChildren = LibraryManager.RootFolder.Children - .OfType<Folder>() - .ToList(); - - return PhysicalLocations.Where(i => !FileSystem.AreEqual(i, Path)).SelectMany(i => GetPhysicalParents(i, rootChildren)).DistinctBy(i => i.Id); - } - - private IEnumerable<Folder> GetPhysicalParents(string path, List<Folder> rootChildren) - { - var result = rootChildren - .Where(i => FileSystem.AreEqual(i.Path, path)) - .ToList(); - - if (result.Count == 0) - { - var folder = LibraryManager.FindByPath(path, true) as Folder; - - if (folder != null) - { - result.Add(folder); - } - } - - return result; - } - - [IgnoreDataMember] - public override bool SupportsPeople - { - get - { - return false; - } - } - } -} diff --git a/MediaBrowser.Controller/Entities/DayOfWeekHelper.cs b/MediaBrowser.Controller/Entities/DayOfWeekHelper.cs deleted file mode 100644 index 80ba206cc6..0000000000 --- a/MediaBrowser.Controller/Entities/DayOfWeekHelper.cs +++ /dev/null @@ -1,71 +0,0 @@ -using MediaBrowser.Model.Configuration; -using System; -using System.Collections.Generic; - -namespace MediaBrowser.Controller.Entities -{ - public static class DayOfWeekHelper - { - public static List<DayOfWeek> GetDaysOfWeek(DynamicDayOfWeek day) - { - return GetDaysOfWeek(new List<DynamicDayOfWeek> { day }); - } - - public static List<DayOfWeek> GetDaysOfWeek(List<DynamicDayOfWeek> days) - { - var list = new List<DayOfWeek>(); - - if (days.Contains(DynamicDayOfWeek.Sunday) || - days.Contains(DynamicDayOfWeek.Weekend) || - days.Contains(DynamicDayOfWeek.Everyday)) - { - list.Add(DayOfWeek.Sunday); - } - - if (days.Contains(DynamicDayOfWeek.Saturday) || - days.Contains(DynamicDayOfWeek.Weekend) || - days.Contains(DynamicDayOfWeek.Everyday)) - { - list.Add(DayOfWeek.Saturday); - } - - if (days.Contains(DynamicDayOfWeek.Monday) || - days.Contains(DynamicDayOfWeek.Weekday) || - days.Contains(DynamicDayOfWeek.Everyday)) - { - list.Add(DayOfWeek.Monday); - } - - if (days.Contains(DynamicDayOfWeek.Monday) || - days.Contains(DynamicDayOfWeek.Weekday) || - days.Contains(DynamicDayOfWeek.Everyday)) - { - list.Add(DayOfWeek.Tuesday - ); - } - - if (days.Contains(DynamicDayOfWeek.Wednesday) || - days.Contains(DynamicDayOfWeek.Weekday) || - days.Contains(DynamicDayOfWeek.Everyday)) - { - list.Add(DayOfWeek.Wednesday); - } - - if (days.Contains(DynamicDayOfWeek.Thursday) || - days.Contains(DynamicDayOfWeek.Weekday) || - days.Contains(DynamicDayOfWeek.Everyday)) - { - list.Add(DayOfWeek.Thursday); - } - - if (days.Contains(DynamicDayOfWeek.Friday) || - days.Contains(DynamicDayOfWeek.Weekday) || - days.Contains(DynamicDayOfWeek.Everyday)) - { - list.Add(DayOfWeek.Friday); - } - - return list; - } - } -} diff --git a/MediaBrowser.Controller/Entities/Extensions.cs b/MediaBrowser.Controller/Entities/Extensions.cs deleted file mode 100644 index 36855a86c1..0000000000 --- a/MediaBrowser.Controller/Entities/Extensions.cs +++ /dev/null @@ -1,46 +0,0 @@ -using MediaBrowser.Model.Entities; -using System; -using System.Linq; -using MediaBrowser.Model.Extensions; - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Class Extensions - /// </summary> - public static class Extensions - { - /// <summary> - /// Adds the trailer URL. - /// </summary> - public static void AddTrailerUrl(this IHasTrailers item, string url) - { - if (string.IsNullOrWhiteSpace(url)) - { - throw new ArgumentNullException("url"); - } - - var current = item.RemoteTrailers.FirstOrDefault(i => string.Equals(i.Url, url, StringComparison.OrdinalIgnoreCase)); - - if (current == null) - { - var mediaUrl = new MediaUrl - { - Url = url - }; - - if (item.RemoteTrailers.Length == 0) - { - item.RemoteTrailers = new[] { mediaUrl }; - } - else - { - var list = item.RemoteTrailers.ToArray(item.RemoteTrailers.Length + 1); - list[list.Length - 1] = mediaUrl; - - item.RemoteTrailers = list; - } - } - } - } -} diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs deleted file mode 100644 index 08b6a123d9..0000000000 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ /dev/null @@ -1,1573 +0,0 @@ -using MediaBrowser.Common.Progress; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Querying; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -using MediaBrowser.Controller.Channels; -using MediaBrowser.Controller.Dto; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.IO; -using MediaBrowser.Model.Channels; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.Extensions; - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Class Folder - /// </summary> - public class Folder : BaseItem - { - public static IUserManager UserManager { get; set; } - public static IUserViewManager UserViewManager { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether this instance is root. - /// </summary> - /// <value><c>true</c> if this instance is root; otherwise, <c>false</c>.</value> - public bool IsRoot { get; set; } - - public LinkedChild[] LinkedChildren { get; set; } - - [IgnoreDataMember] - public DateTime? DateLastMediaAdded { get; set; } - - public Folder() - { - LinkedChildren = EmptyLinkedChildArray; - } - - [IgnoreDataMember] - public override bool SupportsThemeMedia - { - get { return true; } - } - - [IgnoreDataMember] - public virtual bool IsPreSorted - { - get { return false; } - } - - [IgnoreDataMember] - public virtual bool IsPhysicalRoot - { - get { return false; } - } - - [IgnoreDataMember] - public override bool SupportsInheritedParentImages - { - get - { - return true; - } - } - - [IgnoreDataMember] - public override bool SupportsPlayedStatus - { - get - { - return true; - } - } - - /// <summary> - /// Gets a value indicating whether this instance is folder. - /// </summary> - /// <value><c>true</c> if this instance is folder; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public override bool IsFolder - { - get - { - return true; - } - } - - [IgnoreDataMember] - public override bool IsDisplayedAsFolder - { - get - { - return true; - } - } - - [IgnoreDataMember] - public virtual bool SupportsCumulativeRunTimeTicks - { - get - { - return false; - } - } - - [IgnoreDataMember] - public virtual bool SupportsDateLastMediaAdded - { - get - { - return false; - } - } - - public override bool CanDelete() - { - if (IsRoot) - { - return false; - } - - return base.CanDelete(); - } - - public override bool RequiresRefresh() - { - var baseResult = base.RequiresRefresh(); - - if (SupportsCumulativeRunTimeTicks && !RunTimeTicks.HasValue) - { - baseResult = true; - } - - return baseResult; - } - - [IgnoreDataMember] - public override string FileNameWithoutExtension - { - get - { - if (LocationType == LocationType.FileSystem) - { - return System.IO.Path.GetFileName(Path); - } - - return null; - } - } - - protected override bool IsAllowTagFilterEnforced() - { - if (this is ICollectionFolder) - { - return false; - } - if (this is UserView) - { - return false; - } - return true; - } - - [IgnoreDataMember] - protected virtual bool SupportsShortcutChildren - { - get { return false; } - } - - /// <summary> - /// Adds the child. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - /// <exception cref="System.InvalidOperationException">Unable to add + item.Name</exception> - public void AddChild(BaseItem item, CancellationToken cancellationToken) - { - item.SetParent(this); - - if (item.Id == Guid.Empty) - { - item.Id = LibraryManager.GetNewItemId(item.Path, item.GetType()); - } - - if (Children.Any(i => i.Id == item.Id)) - { - throw new ArgumentException(string.Format("A child with the Id {0} already exists.", item.Id)); - } - - if (item.DateCreated == DateTime.MinValue) - { - item.DateCreated = DateTime.UtcNow; - } - if (item.DateModified == DateTime.MinValue) - { - item.DateModified = DateTime.UtcNow; - } - - LibraryManager.CreateItem(item, cancellationToken); - } - - /// <summary> - /// Removes the child. - /// </summary> - /// <param name="item">The item.</param> - public void RemoveChild(BaseItem item) - { - item.SetParent(null); - } - - /// <summary> - /// Gets the actual children. - /// </summary> - /// <value>The actual children.</value> - [IgnoreDataMember] - public virtual IEnumerable<BaseItem> Children - { - get - { - return LoadChildren(); - } - } - - /// <summary> - /// thread-safe access to all recursive children of this folder - without regard to user - /// </summary> - /// <value>The recursive children.</value> - [IgnoreDataMember] - public IEnumerable<BaseItem> RecursiveChildren - { - get { return GetRecursiveChildren(); } - } - - public override bool IsVisible(User user) - { - if (this is ICollectionFolder && !(this is BasePluginFolder)) - { - if (user.Policy.BlockedMediaFolders != null) - { - if (user.Policy.BlockedMediaFolders.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase) || - - // Backwards compatibility - user.Policy.BlockedMediaFolders.Contains(Name, StringComparer.OrdinalIgnoreCase)) - { - return false; - } - } - else - { - if (!user.Policy.EnableAllFolders && !user.Policy.EnabledFolders.Contains(Id.ToString("N"), StringComparer.OrdinalIgnoreCase)) - { - return false; - } - } - } - - return base.IsVisible(user); - } - - /// <summary> - /// Loads our children. Validation will occur externally. - /// We want this sychronous. - /// </summary> - protected virtual List<BaseItem> LoadChildren() - { - //Logger.Debug("Loading children from {0} {1} {2}", GetType().Name, Id, Path); - //just load our children from the repo - the library will be validated and maintained in other processes - return GetCachedChildren(); - } - - public override double? GetRefreshProgress() - { - return ProviderManager.GetRefreshProgress(Id); - } - - public Task ValidateChildren(IProgress<double> progress, CancellationToken cancellationToken) - { - return ValidateChildren(progress, cancellationToken, new MetadataRefreshOptions(new DirectoryService(Logger, FileSystem))); - } - - /// <summary> - /// Validates that the children of the folder still exist - /// </summary> - /// <param name="progress">The progress.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="metadataRefreshOptions">The metadata refresh options.</param> - /// <param name="recursive">if set to <c>true</c> [recursive].</param> - /// <returns>Task.</returns> - public Task ValidateChildren(IProgress<double> progress, CancellationToken cancellationToken, MetadataRefreshOptions metadataRefreshOptions, bool recursive = true) - { - return ValidateChildrenInternal(progress, cancellationToken, recursive, true, metadataRefreshOptions, metadataRefreshOptions.DirectoryService); - } - - private Dictionary<Guid, BaseItem> GetActualChildrenDictionary() - { - var dictionary = new Dictionary<Guid, BaseItem>(); - - var childrenList = Children.ToList(); - - foreach (var child in childrenList) - { - var id = child.Id; - if (dictionary.ContainsKey(id)) - { - Logger.Error("Found folder containing items with duplicate id. Path: {0}, Child Name: {1}", - Path ?? Name, - child.Path ?? child.Name); - } - else - { - dictionary[id] = child; - } - } - - return dictionary; - } - - protected override void TriggerOnRefreshStart() - { - } - - protected override void TriggerOnRefreshComplete() - { - } - - /// <summary> - /// Validates the children internal. - /// </summary> - /// <param name="progress">The progress.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="recursive">if set to <c>true</c> [recursive].</param> - /// <param name="refreshChildMetadata">if set to <c>true</c> [refresh child metadata].</param> - /// <param name="refreshOptions">The refresh options.</param> - /// <param name="directoryService">The directory service.</param> - /// <returns>Task.</returns> - protected virtual async Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService) - { - if (recursive) - { - ProviderManager.OnRefreshStart(this); - } - - try - { - await ValidateChildrenInternal2(progress, cancellationToken, recursive, refreshChildMetadata, refreshOptions, directoryService).ConfigureAwait(false); - } - finally - { - if (recursive) - { - ProviderManager.OnRefreshComplete(this); - } - } - } - - private async Task ValidateChildrenInternal2(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService) - { - var locationType = LocationType; - - cancellationToken.ThrowIfCancellationRequested(); - - var validChildren = new List<BaseItem>(); - var validChildrenNeedGeneration = false; - - var allLibraryPaths = LibraryManager - .GetVirtualFolders() - .SelectMany(i => i.Locations) - .ToList(); - - if (locationType != LocationType.Remote && locationType != LocationType.Virtual) - { - IEnumerable<BaseItem> nonCachedChildren; - - try - { - nonCachedChildren = GetNonCachedChildren(directoryService); - } - catch (IOException ex) - { - nonCachedChildren = new BaseItem[] { }; - - Logger.ErrorException("Error getting file system entries for {0}", ex, Path); - } - - if (nonCachedChildren == null) return; //nothing to validate - - progress.Report(5); - - if (recursive) - { - ProviderManager.OnRefreshProgress(this, 5); - } - - //build a dictionary of the current children we have now by Id so we can compare quickly and easily - var currentChildren = GetActualChildrenDictionary(); - - //create a list for our validated children - var newItems = new List<BaseItem>(); - - cancellationToken.ThrowIfCancellationRequested(); - - foreach (var child in nonCachedChildren) - { - BaseItem currentChild; - - if (currentChildren.TryGetValue(child.Id, out currentChild)) - { - validChildren.Add(currentChild); - - if (currentChild.UpdateFromResolvedItem(child) > ItemUpdateType.None) - { - currentChild.UpdateToRepository(ItemUpdateType.MetadataImport, cancellationToken); - } - - continue; - } - - // Brand new item - needs to be added - child.SetParent(this); - newItems.Add(child); - validChildren.Add(child); - } - - // If any items were added or removed.... - if (newItems.Count > 0 || currentChildren.Count != validChildren.Count) - { - // That's all the new and changed ones - now see if there are any that are missing - var itemsRemoved = currentChildren.Values.Except(validChildren).ToList(); - var actualRemovals = new List<BaseItem>(); - - foreach (var item in itemsRemoved) - { - var itemLocationType = item.LocationType; - if (itemLocationType == LocationType.Virtual || - itemLocationType == LocationType.Remote) - { - } - - else if (!string.IsNullOrEmpty(item.Path) && IsPathOffline(item.Path, allLibraryPaths)) - { - } - else - { - actualRemovals.Add(item); - } - } - - if (actualRemovals.Count > 0) - { - foreach (var item in actualRemovals) - { - Logger.Debug("Removed item: " + item.Path); - - item.SetParent(null); - await LibraryManager.DeleteItem(item, new DeleteOptions { DeleteFileLocation = false }).ConfigureAwait(false); - LibraryManager.ReportItemRemoved(item, this); - } - } - - LibraryManager.CreateItems(newItems, this, cancellationToken); - } - } - else - { - validChildrenNeedGeneration = true; - } - - progress.Report(10); - - if (recursive) - { - ProviderManager.OnRefreshProgress(this, 10); - } - - cancellationToken.ThrowIfCancellationRequested(); - - if (recursive) - { - using (var innerProgress = new ActionableProgress<double>()) - { - var folder = this; - innerProgress.RegisterAction(p => - { - double newPct = .80 * p + 10; - progress.Report(newPct); - ProviderManager.OnRefreshProgress(folder, newPct); - }); - - if (validChildrenNeedGeneration) - { - validChildren = Children.ToList(); - validChildrenNeedGeneration = false; - } - - await ValidateSubFolders(validChildren.OfType<Folder>().ToList(), directoryService, innerProgress, cancellationToken).ConfigureAwait(false); - } - } - - if (refreshChildMetadata) - { - progress.Report(90); - - if (recursive) - { - ProviderManager.OnRefreshProgress(this, 90); - } - - var container = this as IMetadataContainer; - - using (var innerProgress = new ActionableProgress<double>()) - { - var folder = this; - innerProgress.RegisterAction(p => - { - double newPct = .10 * p + 90; - progress.Report(newPct); - if (recursive) - { - ProviderManager.OnRefreshProgress(folder, newPct); - } - }); - - if (container != null) - { - await container.RefreshAllMetadata(refreshOptions, innerProgress, cancellationToken).ConfigureAwait(false); - } - else - { - if (validChildrenNeedGeneration) - { - validChildren = Children.ToList(); - } - - await RefreshMetadataRecursive(validChildren, refreshOptions, recursive, innerProgress, cancellationToken); - } - } - } - } - - private async Task RefreshMetadataRecursive(List<BaseItem> children, MetadataRefreshOptions refreshOptions, bool recursive, IProgress<double> progress, CancellationToken cancellationToken) - { - var numComplete = 0; - var count = children.Count; - double currentPercent = 0; - - foreach (var child in children) - { - cancellationToken.ThrowIfCancellationRequested(); - - using (var innerProgress = new ActionableProgress<double>()) - { - // Avoid implicitly captured closure - var currentInnerPercent = currentPercent; - - innerProgress.RegisterAction(p => - { - double innerPercent = currentInnerPercent; - innerPercent += p / (count); - progress.Report(innerPercent); - }); - - await RefreshChildMetadata(child, refreshOptions, recursive && child.IsFolder, innerProgress, cancellationToken) - .ConfigureAwait(false); - } - - numComplete++; - double percent = numComplete; - percent /= count; - percent *= 100; - currentPercent = percent; - - progress.Report(percent); - } - } - - private async Task RefreshChildMetadata(BaseItem child, MetadataRefreshOptions refreshOptions, bool recursive, IProgress<double> progress, CancellationToken cancellationToken) - { - var container = child as IMetadataContainer; - - if (container != null) - { - await container.RefreshAllMetadata(refreshOptions, progress, cancellationToken).ConfigureAwait(false); - } - else - { - if (refreshOptions.RefreshItem(child)) - { - await child.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); - } - - if (recursive) - { - var folder = child as Folder; - - if (folder != null) - { - await folder.RefreshMetadataRecursive(folder.Children.ToList(), refreshOptions, true, progress, cancellationToken); - } - } - } - } - - /// <summary> - /// Refreshes the children. - /// </summary> - /// <param name="children">The children.</param> - /// <param name="directoryService">The directory service.</param> - /// <param name="progress">The progress.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - private async Task ValidateSubFolders(IList<Folder> children, IDirectoryService directoryService, IProgress<double> progress, CancellationToken cancellationToken) - { - var numComplete = 0; - var count = children.Count; - double currentPercent = 0; - - foreach (var child in children) - { - cancellationToken.ThrowIfCancellationRequested(); - - using (var innerProgress = new ActionableProgress<double>()) - { - // Avoid implicitly captured closure - var currentInnerPercent = currentPercent; - - innerProgress.RegisterAction(p => - { - double innerPercent = currentInnerPercent; - innerPercent += p / (count); - progress.Report(innerPercent); - }); - - await child.ValidateChildrenInternal(innerProgress, cancellationToken, true, false, null, directoryService) - .ConfigureAwait(false); - } - - numComplete++; - double percent = numComplete; - percent /= count; - percent *= 100; - currentPercent = percent; - - progress.Report(percent); - } - } - - public static bool IsPathOffline(string path, List<string> allLibraryPaths) - { - //if (FileSystem.FileExists(path)) - //{ - // return false; - //} - - var originalPath = path; - - // Depending on whether the path is local or unc, it may return either null or '\' at the top - while (!string.IsNullOrWhiteSpace(path) && path.Length > 1) - { - if (FileSystem.DirectoryExists(path)) - { - return false; - } - - if (allLibraryPaths.Contains(path, StringComparer.OrdinalIgnoreCase)) - { - return true; - } - - path = FileSystem.GetDirectoryName(path); - } - - return allLibraryPaths.Any(i => ContainsPath(i, originalPath)); - } - - private static bool ContainsPath(string parent, string path) - { - return FileSystem.AreEqual(parent, path) || FileSystem.ContainsSubPath(parent, path); - } - - /// <summary> - /// Get the children of this folder from the actual file system - /// </summary> - /// <returns>IEnumerable{BaseItem}.</returns> - protected virtual IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService) - { - var collectionType = LibraryManager.GetContentType(this); - var libraryOptions = LibraryManager.GetLibraryOptions(this); - - return LibraryManager.ResolvePaths(GetFileSystemChildren(directoryService), directoryService, this, libraryOptions, collectionType); - } - - /// <summary> - /// Get our children from the repo - stubbed for now - /// </summary> - /// <returns>IEnumerable{BaseItem}.</returns> - protected List<BaseItem> GetCachedChildren() - { - return ItemRepository.GetItemList(new InternalItemsQuery - { - Parent = this, - GroupByPresentationUniqueKey = false, - DtoOptions = new DtoOptions(true) - }); - } - - public virtual int GetChildCount(User user) - { - if (LinkedChildren.Length > 0) - { - if (!(this is ICollectionFolder)) - { - return GetChildren(user, true).Count; - } - } - - var result = GetItems(new InternalItemsQuery(user) - { - Recursive = false, - Limit = 0, - Parent = this, - DtoOptions = new DtoOptions(false) - { - EnableImages = false - } - - }); - - return result.TotalRecordCount; - } - - public virtual int GetRecursiveChildCount(User user) - { - return GetItems(new InternalItemsQuery(user) - { - Recursive = true, - IsFolder = false, - IsVirtualItem = false, - EnableTotalRecordCount = true, - Limit = 0, - DtoOptions = new DtoOptions(false) - { - EnableImages = false - } - - }).TotalRecordCount; - } - - public QueryResult<BaseItem> QueryRecursive(InternalItemsQuery query) - { - var user = query.User; - - if (!query.ForceDirect && RequiresPostFiltering(query)) - { - IEnumerable<BaseItem> items; - Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager); - - if (query.User == null) - { - items = GetRecursiveChildren(filter); - } - else - { - items = GetRecursiveChildren(user, query); - } - - return PostFilterAndSort(items, query, true, true); - } - - if (!(this is UserRootFolder) && !(this is AggregateFolder)) - { - if (!query.ParentId.HasValue) - { - query.Parent = this; - } - } - - if (RequiresPostFiltering2(query)) - { - return QueryWithPostFiltering2(query); - } - - return LibraryManager.GetItemsResult(query); - } - - private QueryResult<BaseItem> QueryWithPostFiltering2(InternalItemsQuery query) - { - var startIndex = query.StartIndex; - var limit = query.Limit; - - query.StartIndex = null; - query.Limit = null; - - var itemsList = LibraryManager.GetItemList(query); - var user = query.User; - - if (user != null) - { - // needed for boxsets - itemsList = itemsList.Where(i => i.IsVisibleStandalone(query.User)).ToList(); - } - - BaseItem[] returnItems; - int totalCount = 0; - - if (query.EnableTotalRecordCount) - { - var itemsArray = itemsList.ToArray(); - totalCount = itemsArray.Length; - returnItems = itemsArray; - } - else - { - returnItems = itemsList.ToArray(); - } - - if (limit.HasValue) - { - returnItems = returnItems.Skip(startIndex ?? 0).Take(limit.Value).ToArray(); - } - else if (startIndex.HasValue) - { - returnItems = returnItems.Skip(startIndex.Value).ToArray(); - } - - return new QueryResult<BaseItem> - { - TotalRecordCount = totalCount, - Items = returnItems.ToArray() - }; - } - - private bool RequiresPostFiltering2(InternalItemsQuery query) - { - if (query.IncludeItemTypes.Length == 1 && string.Equals(query.IncludeItemTypes[0], typeof(BoxSet).Name, StringComparison.OrdinalIgnoreCase)) - { - Logger.Debug("Query requires post-filtering due to BoxSet query"); - return true; - } - - return false; - } - - private bool RequiresPostFiltering(InternalItemsQuery query) - { - if (LinkedChildren.Length > 0) - { - if (!(this is ICollectionFolder)) - { - Logger.Debug("Query requires post-filtering due to LinkedChildren. Type: " + GetType().Name); - return true; - } - } - - if (query.IsInBoxSet.HasValue) - { - Logger.Debug("Query requires post-filtering due to IsInBoxSet"); - return true; - } - - // Filter by Video3DFormat - if (query.Is3D.HasValue) - { - Logger.Debug("Query requires post-filtering due to Is3D"); - return true; - } - - if (query.HasOfficialRating.HasValue) - { - Logger.Debug("Query requires post-filtering due to HasOfficialRating"); - return true; - } - - if (query.IsPlaceHolder.HasValue) - { - Logger.Debug("Query requires post-filtering due to IsPlaceHolder"); - return true; - } - - if (query.HasSpecialFeature.HasValue) - { - Logger.Debug("Query requires post-filtering due to HasSpecialFeature"); - return true; - } - - if (query.HasSubtitles.HasValue) - { - Logger.Debug("Query requires post-filtering due to HasSubtitles"); - return true; - } - - if (query.HasTrailer.HasValue) - { - Logger.Debug("Query requires post-filtering due to HasTrailer"); - return true; - } - - // Filter by VideoType - if (query.VideoTypes.Length > 0) - { - Logger.Debug("Query requires post-filtering due to VideoTypes"); - return true; - } - - // Apply person filter - if (query.ItemIdsFromPersonFilters != null) - { - Logger.Debug("Query requires post-filtering due to ItemIdsFromPersonFilters"); - return true; - } - - if (UserViewBuilder.CollapseBoxSetItems(query, this, query.User, ConfigurationManager)) - { - Logger.Debug("Query requires post-filtering due to CollapseBoxSetItems"); - return true; - } - - if (!string.IsNullOrWhiteSpace(query.AdjacentTo)) - { - Logger.Debug("Query requires post-filtering due to AdjacentTo"); - return true; - } - - if (query.SeriesStatuses.Length > 0) - { - Logger.Debug("Query requires post-filtering due to SeriesStatuses"); - return true; - } - - if (query.AiredDuringSeason.HasValue) - { - Logger.Debug("Query requires post-filtering due to AiredDuringSeason"); - return true; - } - - if (query.IsPlayed.HasValue) - { - if (query.IncludeItemTypes.Length == 1 && query.IncludeItemTypes.Contains(typeof(Series).Name)) - { - Logger.Debug("Query requires post-filtering due to IsPlayed"); - return true; - } - } - - return false; - } - - public QueryResult<BaseItem> GetItems(InternalItemsQuery query) - { - if (query.ItemIds.Length > 0) - { - var result = LibraryManager.GetItemsResult(query); - - if (query.OrderBy.Length == 0) - { - var ids = query.ItemIds.ToList(); - - // Try to preserve order - result.Items = result.Items.OrderBy(i => ids.IndexOf(i.Id.ToString("N"))).ToArray(); - } - return result; - } - - return GetItemsInternal(query); - } - - public BaseItem[] GetItemList(InternalItemsQuery query) - { - query.EnableTotalRecordCount = false; - - if (query.ItemIds.Length > 0) - { - var result = LibraryManager.GetItemList(query); - - if (query.OrderBy.Length == 0) - { - var ids = query.ItemIds.ToList(); - - // Try to preserve order - return result.OrderBy(i => ids.IndexOf(i.Id.ToString("N"))).ToArray(); - } - return result.ToArray(result.Count); - } - - return GetItemsInternal(query).Items; - } - - protected virtual QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query) - { - if (SourceType == SourceType.Channel) - { - try - { - // Don't blow up here because it could cause parent screens with other content to fail - return ChannelManager.GetChannelItemsInternal(new ChannelItemQuery - { - ChannelId = ChannelId, - FolderId = Id.ToString("N"), - Limit = query.Limit, - StartIndex = query.StartIndex, - UserId = query.User.Id.ToString("N"), - OrderBy = query.OrderBy - - }, new SimpleProgress<double>(), CancellationToken.None).Result; - } - catch - { - // Already logged at lower levels - return new QueryResult<BaseItem>(); - } - } - - if (query.Recursive) - { - return QueryRecursive(query); - } - - var user = query.User; - - Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager); - - IEnumerable<BaseItem> items; - - if (query.User == null) - { - items = query.Recursive - ? GetRecursiveChildren(filter) - : Children.Where(filter); - } - else - { - items = query.Recursive - ? GetRecursiveChildren(user, query) - : GetChildren(user, true).Where(filter); - } - - return PostFilterAndSort(items, query, true, true); - } - - protected QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, InternalItemsQuery query, bool collapseBoxSetItems, bool enableSorting) - { - return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager, ConfigurationManager, collapseBoxSetItems, enableSorting); - } - - public virtual List<BaseItem> GetChildren(User user, bool includeLinkedChildren) - { - if (user == null) - { - throw new ArgumentNullException(); - } - - //the true root should return our users root folder children - if (IsPhysicalRoot) return user.RootFolder.GetChildren(user, includeLinkedChildren); - - var result = new Dictionary<Guid, BaseItem>(); - - AddChildren(user, includeLinkedChildren, result, false, null); - - return result.Values.ToList(); - } - - protected virtual IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user) - { - return Children; - } - - /// <summary> - /// Adds the children to list. - /// </summary> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> - private void AddChildren(User user, bool includeLinkedChildren, Dictionary<Guid, BaseItem> result, bool recursive, InternalItemsQuery query) - { - foreach (var child in GetEligibleChildrenForRecursiveChildren(user)) - { - if (child.IsVisible(user)) - { - if (query == null || UserViewBuilder.FilterItem(child, query)) - { - result[child.Id] = child; - } - - if (recursive && child.IsFolder) - { - var folder = (Folder)child; - - folder.AddChildren(user, includeLinkedChildren, result, true, query); - } - } - } - - if (includeLinkedChildren) - { - foreach (var child in GetLinkedChildren(user)) - { - if (child.IsVisible(user)) - { - if (query == null || UserViewBuilder.FilterItem(child, query)) - { - result[child.Id] = child; - } - } - } - } - } - - /// <summary> - /// Gets allowed recursive children of an item - /// </summary> - /// <param name="user">The user.</param> - /// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param> - /// <returns>IEnumerable{BaseItem}.</returns> - /// <exception cref="System.ArgumentNullException"></exception> - public IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = true) - { - return GetRecursiveChildren(user, null); - } - - public virtual IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query) - { - if (user == null) - { - throw new ArgumentNullException("user"); - } - - var result = new Dictionary<Guid, BaseItem>(); - - AddChildren(user, true, result, true, query); - - return result.Values; - } - - /// <summary> - /// Gets the recursive children. - /// </summary> - /// <returns>IList{BaseItem}.</returns> - public IList<BaseItem> GetRecursiveChildren() - { - return GetRecursiveChildren(true); - } - - public IList<BaseItem> GetRecursiveChildren(bool includeLinkedChildren) - { - return GetRecursiveChildren(i => true, includeLinkedChildren); - } - - public IList<BaseItem> GetRecursiveChildren(Func<BaseItem, bool> filter) - { - return GetRecursiveChildren(filter, true); - } - - public IList<BaseItem> GetRecursiveChildren(Func<BaseItem, bool> filter, bool includeLinkedChildren) - { - var result = new Dictionary<Guid, BaseItem>(); - - AddChildrenToList(result, includeLinkedChildren, true, filter); - - return result.Values.ToList(); - } - - /// <summary> - /// Adds the children to list. - /// </summary> - private void AddChildrenToList(Dictionary<Guid, BaseItem> result, bool includeLinkedChildren, bool recursive, Func<BaseItem, bool> filter) - { - foreach (var child in Children) - { - if (filter == null || filter(child)) - { - result[child.Id] = child; - } - - if (recursive && child.IsFolder) - { - var folder = (Folder)child; - - // We can only support includeLinkedChildren for the first folder, or we might end up stuck in a loop of linked items - folder.AddChildrenToList(result, false, true, filter); - } - } - - if (includeLinkedChildren) - { - foreach (var child in GetLinkedChildren()) - { - if (filter == null || filter(child)) - { - result[child.Id] = child; - } - } - } - } - - - /// <summary> - /// Gets the linked children. - /// </summary> - /// <returns>IEnumerable{BaseItem}.</returns> - public List<BaseItem> GetLinkedChildren() - { - var linkedChildren = LinkedChildren; - var list = new List<BaseItem>(linkedChildren.Length); - - foreach (var i in linkedChildren) - { - var child = GetLinkedChild(i); - - if (child != null) - { - list.Add(child); - } - } - return list; - } - - protected virtual bool FilterLinkedChildrenPerUser - { - get - { - return false; - } - } - - public List<BaseItem> GetLinkedChildren(User user) - { - if (!FilterLinkedChildrenPerUser || user == null) - { - return GetLinkedChildren(); - } - - var linkedChildren = LinkedChildren; - var list = new List<BaseItem>(linkedChildren.Length); - - if (linkedChildren.Length == 0) - { - return list; - } - - var allUserRootChildren = user.RootFolder.Children.OfType<Folder>().ToList(); - - var collectionFolderIds = allUserRootChildren - .OfType<CollectionFolder>() - .Where(i => i.IsVisible(user)) - .Select(i => i.Id) - .ToList(); - - foreach (var i in linkedChildren) - { - var child = GetLinkedChild(i); - - if (child == null) - { - continue; - } - - var childOwner = child.IsOwnedItem ? (child.GetOwner() ?? child) : child; - - if (childOwner != null && !(child is IItemByName)) - { - var childLocationType = childOwner.LocationType; - if (childLocationType == LocationType.Remote || childLocationType == LocationType.Virtual) - { - if (!childOwner.IsVisibleStandalone(user)) - { - continue; - } - } - else if (childLocationType == LocationType.FileSystem) - { - var itemCollectionFolderIds = - LibraryManager.GetCollectionFolders(childOwner, allUserRootChildren).Select(f => f.Id); - - if (!itemCollectionFolderIds.Any(collectionFolderIds.Contains)) - { - continue; - } - } - } - - list.Add(child); - } - - return list; - } - - /// <summary> - /// Gets the linked children. - /// </summary> - /// <returns>IEnumerable{BaseItem}.</returns> - public IEnumerable<Tuple<LinkedChild, BaseItem>> GetLinkedChildrenInfos() - { - return LinkedChildren - .Select(i => new Tuple<LinkedChild, BaseItem>(i, GetLinkedChild(i))) - .Where(i => i.Item2 != null); - } - - [IgnoreDataMember] - protected override bool SupportsOwnedItems - { - get - { - return base.SupportsOwnedItems || SupportsShortcutChildren; - } - } - - protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) - { - var changesFound = false; - - if (LocationType == LocationType.FileSystem) - { - if (RefreshLinkedChildren(fileSystemChildren)) - { - changesFound = true; - } - } - - var baseHasChanges = await base.RefreshedOwnedItems(options, fileSystemChildren, cancellationToken).ConfigureAwait(false); - - return baseHasChanges || changesFound; - } - - /// <summary> - /// Refreshes the linked children. - /// </summary> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> - protected virtual bool RefreshLinkedChildren(IEnumerable<FileSystemMetadata> fileSystemChildren) - { - if (SupportsShortcutChildren) - { - var newShortcutLinks = fileSystemChildren - .Where(i => !i.IsDirectory && FileSystem.IsShortcut(i.FullName)) - .Select(i => - { - try - { - Logger.Debug("Found shortcut at {0}", i.FullName); - - var resolvedPath = FileSystem.ResolveShortcut(i.FullName); - - if (!string.IsNullOrEmpty(resolvedPath)) - { - return new LinkedChild - { - Path = resolvedPath, - Type = LinkedChildType.Shortcut - }; - } - - Logger.Error("Error resolving shortcut {0}", i.FullName); - - return null; - } - catch (IOException ex) - { - Logger.ErrorException("Error resolving shortcut {0}", ex, i.FullName); - return null; - } - }) - .Where(i => i != null) - .ToList(); - - var currentShortcutLinks = LinkedChildren.Where(i => i.Type == LinkedChildType.Shortcut).ToList(); - - if (!newShortcutLinks.SequenceEqual(currentShortcutLinks, new LinkedChildComparer(FileSystem))) - { - Logger.Info("Shortcut links have changed for {0}", Path); - - newShortcutLinks.AddRange(LinkedChildren.Where(i => i.Type == LinkedChildType.Manual)); - LinkedChildren = newShortcutLinks.ToArray(newShortcutLinks.Count); - return true; - } - } - - foreach (var child in LinkedChildren) - { - // Reset the cached value - child.ItemId = null; - } - - return false; - } - - /// <summary> - /// Marks the played. - /// </summary> - /// <param name="user">The user.</param> - /// <param name="datePlayed">The date played.</param> - /// <param name="resetPosition">if set to <c>true</c> [reset position].</param> - /// <returns>Task.</returns> - public override void MarkPlayed(User user, - DateTime? datePlayed, - bool resetPosition) - { - var query = new InternalItemsQuery - { - User = user, - Recursive = true, - IsFolder = false, - EnableTotalRecordCount = false - }; - - if (!user.Configuration.DisplayMissingEpisodes) - { - query.IsVirtualItem = false; - } - - var itemsResult = GetItemList(query); - - // Sweep through recursively and update status - foreach (var item in itemsResult) - { - if (item.IsVirtualItem) - { - // The querying doesn't support virtual unaired - var episode = item as Episode; - if (episode != null && episode.IsUnaired) - { - continue; - } - } - - item.MarkPlayed(user, datePlayed, resetPosition); - } - } - - /// <summary> - /// Marks the unplayed. - /// </summary> - /// <param name="user">The user.</param> - /// <returns>Task.</returns> - public override void MarkUnplayed(User user) - { - var itemsResult = GetItemList(new InternalItemsQuery - { - User = user, - Recursive = true, - IsFolder = false, - EnableTotalRecordCount = false - - }); - - // Sweep through recursively and update status - foreach (var item in itemsResult) - { - item.MarkUnplayed(user); - } - } - - public override bool IsPlayed(User user) - { - var itemsResult = GetItemList(new InternalItemsQuery(user) - { - Recursive = true, - IsFolder = false, - IsVirtualItem = false, - EnableTotalRecordCount = false - - }); - - return itemsResult - .All(i => i.IsPlayed(user)); - } - - public override bool IsUnplayed(User user) - { - return !IsPlayed(user); - } - - [IgnoreDataMember] - public virtual bool SupportsUserDataFromChildren - { - get - { - // These are just far too slow. - if (this is ICollectionFolder) - { - return false; - } - if (this is UserView) - { - return false; - } - if (this is UserRootFolder) - { - return false; - } - if (this is Channel) - { - return false; - } - if (SourceType != SourceType.Library) - { - return false; - } - var iItemByName = this as IItemByName; - if (iItemByName != null) - { - var hasDualAccess = this as IHasDualAccess; - if (hasDualAccess == null || hasDualAccess.IsAccessedByName) - { - return false; - } - } - - return true; - } - } - - public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user, ItemFields[] fields) - { - if (!SupportsUserDataFromChildren) - { - return; - } - - if (itemDto != null) - { - if (fields.Contains(ItemFields.RecursiveItemCount)) - { - itemDto.RecursiveItemCount = GetRecursiveChildCount(user); - } - } - - if (SupportsPlayedStatus) - { - var unplayedQueryResult = GetItems(new InternalItemsQuery(user) - { - Recursive = true, - IsFolder = false, - IsVirtualItem = false, - EnableTotalRecordCount = true, - Limit = 0, - IsPlayed = false, - DtoOptions = new DtoOptions(false) - { - EnableImages = false - } - - }); - - double unplayedCount = unplayedQueryResult.TotalRecordCount; - - dto.UnplayedItemCount = unplayedQueryResult.TotalRecordCount; - - if (itemDto != null && itemDto.RecursiveItemCount.HasValue) - { - if (itemDto.RecursiveItemCount.Value > 0) - { - var unplayedPercentage = (unplayedCount / itemDto.RecursiveItemCount.Value) * 100; - dto.PlayedPercentage = 100 - unplayedPercentage; - dto.Played = dto.PlayedPercentage.Value >= 100; - } - } - else - { - dto.Played = (dto.UnplayedItemCount ?? 0) == 0; - } - } - } - } -}
\ No newline at end of file diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs deleted file mode 100644 index bead0ef955..0000000000 --- a/MediaBrowser.Controller/Entities/Game.cs +++ /dev/null @@ -1,130 +0,0 @@ -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Entities; -using System; -using System.Collections.Generic; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Controller.Entities -{ - public class Game : BaseItem, IHasTrailers, IHasScreenshots, ISupportsPlaceHolders, IHasLookupInfo<GameInfo> - { - public Game() - { - MultiPartGameFiles = EmptyStringArray; - RemoteTrailers = EmptyMediaUrlArray; - LocalTrailerIds = EmptyGuidArray; - RemoteTrailerIds = EmptyGuidArray; - } - - public Guid[] LocalTrailerIds { get; set; } - public Guid[] RemoteTrailerIds { get; set; } - - public override bool CanDownload() - { - var locationType = LocationType; - return locationType != LocationType.Remote && - locationType != LocationType.Virtual; - } - - [IgnoreDataMember] - public override bool SupportsThemeMedia - { - get { return true; } - } - - [IgnoreDataMember] - public override bool SupportsPeople - { - get { return false; } - } - - /// <summary> - /// Gets or sets the remote trailers. - /// </summary> - /// <value>The remote trailers.</value> - public MediaUrl[] RemoteTrailers { get; set; } - - /// <summary> - /// Gets the type of the media. - /// </summary> - /// <value>The type of the media.</value> - [IgnoreDataMember] - public override string MediaType - { - get { return Model.Entities.MediaType.Game; } - } - - /// <summary> - /// Gets or sets the players supported. - /// </summary> - /// <value>The players supported.</value> - public int? PlayersSupported { get; set; } - - /// <summary> - /// Gets a value indicating whether this instance is place holder. - /// </summary> - /// <value><c>true</c> if this instance is place holder; otherwise, <c>false</c>.</value> - public bool IsPlaceHolder { get; set; } - - /// <summary> - /// Gets or sets the game system. - /// </summary> - /// <value>The game system.</value> - public string GameSystem { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether this instance is multi part. - /// </summary> - /// <value><c>true</c> if this instance is multi part; otherwise, <c>false</c>.</value> - public bool IsMultiPart { get; set; } - - /// <summary> - /// Holds the paths to the game files in the event this is a multipart game - /// </summary> - public string[] MultiPartGameFiles { get; set; } - - public override List<string> GetUserDataKeys() - { - var list = base.GetUserDataKeys(); - var id = this.GetProviderId(MetadataProviders.Gamesdb); - - if (!string.IsNullOrEmpty(id)) - { - list.Insert(0, "Game-Gamesdb-" + id); - } - return list; - } - - public override IEnumerable<FileSystemMetadata> GetDeletePaths() - { - if (!IsInMixedFolder) - { - return new[] { - new FileSystemMetadata - { - FullName = FileSystem.GetDirectoryName(Path), - IsDirectory = true - } - }; - } - - return base.GetDeletePaths(); - } - - public override UnratedItem GetBlockUnratedType() - { - return UnratedItem.Game; - } - - public GameInfo GetLookupInfo() - { - var id = GetItemLookupInfo<GameInfo>(); - - id.GameSystem = GameSystem; - - return id; - } - } -} diff --git a/MediaBrowser.Controller/Entities/GameGenre.cs b/MediaBrowser.Controller/Entities/GameGenre.cs deleted file mode 100644 index 6dc85f3e53..0000000000 --- a/MediaBrowser.Controller/Entities/GameGenre.cs +++ /dev/null @@ -1,141 +0,0 @@ -using System; -using System.Collections.Generic; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.Extensions; -using MediaBrowser.Model.Extensions; - -namespace MediaBrowser.Controller.Entities -{ - public class GameGenre : BaseItem, IItemByName - { - public override List<string> GetUserDataKeys() - { - var list = base.GetUserDataKeys(); - - list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics()); - return list; - } - - public override string CreatePresentationUniqueKey() - { - return GetUserDataKeys()[0]; - } - - public override double? GetDefaultPrimaryImageAspectRatio() - { - return 1; - } - - /// <summary> - /// Returns the folder containing the item. - /// If the item is a folder, it returns the folder itself - /// </summary> - /// <value>The containing folder path.</value> - [IgnoreDataMember] - public override string ContainingFolderPath - { - get - { - return Path; - } - } - - [IgnoreDataMember] - public override bool SupportsAncestors - { - get - { - return false; - } - } - - /// <summary> - /// Gets a value indicating whether this instance is owned item. - /// </summary> - /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public override bool IsOwnedItem - { - get - { - return false; - } - } - - public override bool IsSaveLocalMetadataEnabled() - { - return true; - } - - public override bool CanDelete() - { - return false; - } - - public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query) - { - query.GenreIds = new[] { Id.ToString("N") }; - query.IncludeItemTypes = new[] { typeof(Game).Name }; - - return LibraryManager.GetItemList(query); - } - - [IgnoreDataMember] - public override bool SupportsPeople - { - get - { - return false; - } - } - - public static string GetPath(string name) - { - return GetPath(name, true); - } - - public static string GetPath(string name, bool normalizeName) - { - // Trim the period at the end because windows will have a hard time with that - var validName = normalizeName ? - FileSystem.GetValidFilename(name).Trim().TrimEnd('.') : - name; - - return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.GameGenrePath, validName); - } - - private string GetRebasedPath() - { - return GetPath(System.IO.Path.GetFileName(Path), false); - } - - public override bool RequiresRefresh() - { - var newPath = GetRebasedPath(); - if (!string.Equals(Path, newPath, StringComparison.Ordinal)) - { - Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath); - return true; - } - return base.RequiresRefresh(); - } - - /// <summary> - /// This is called before any metadata refresh and returns true or false indicating if changes were made - /// </summary> - public override bool BeforeMetadataRefresh() - { - var hasChanges = base.BeforeMetadataRefresh(); - - var newPath = GetRebasedPath(); - if (!string.Equals(Path, newPath, StringComparison.Ordinal)) - { - Path = newPath; - hasChanges = true; - } - - return hasChanges; - } - } -} diff --git a/MediaBrowser.Controller/Entities/GameSystem.cs b/MediaBrowser.Controller/Entities/GameSystem.cs deleted file mode 100644 index c940b59531..0000000000 --- a/MediaBrowser.Controller/Entities/GameSystem.cs +++ /dev/null @@ -1,101 +0,0 @@ -using MediaBrowser.Model.Serialization; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Configuration; -using System; -using System.Collections.Generic; -using MediaBrowser.Model.Users; - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Class GameSystem - /// </summary> - public class GameSystem : Folder, IHasLookupInfo<GameSystemInfo> - { - /// <summary> - /// Return the id that should be used to key display prefs for this item. - /// Default is based on the type for everything except actual generic folders. - /// </summary> - /// <value>The display prefs id.</value> - [IgnoreDataMember] - public override Guid DisplayPreferencesId - { - get - { - return Id; - } - } - - [IgnoreDataMember] - public override bool SupportsPlayedStatus - { - get - { - return false; - } - } - - [IgnoreDataMember] - public override bool SupportsInheritedParentImages - { - get - { - return false; - } - } - - public override double? GetDefaultPrimaryImageAspectRatio() - { - double value = 16; - value /= 9; - - return value; - } - - /// <summary> - /// Gets or sets the game system. - /// </summary> - /// <value>The game system.</value> - public string GameSystemName { get; set; } - - public override List<string> GetUserDataKeys() - { - var list = base.GetUserDataKeys(); - - if (!string.IsNullOrEmpty(GameSystemName)) - { - list.Insert(0, "GameSystem-" + GameSystemName); - } - return list; - } - - protected override bool GetBlockUnratedValue(UserPolicy config) - { - // Don't block. Determine by game - return false; - } - - public override UnratedItem GetBlockUnratedType() - { - return UnratedItem.Game; - } - - public GameSystemInfo GetLookupInfo() - { - var id = GetItemLookupInfo<GameSystemInfo>(); - - id.Path = Path; - - return id; - } - - [IgnoreDataMember] - public override bool SupportsPeople - { - get - { - return false; - } - } - } -} diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs deleted file mode 100644 index 569a0dfb8b..0000000000 --- a/MediaBrowser.Controller/Entities/Genre.cs +++ /dev/null @@ -1,153 +0,0 @@ -using MediaBrowser.Model.Serialization; -using MediaBrowser.Controller.Entities.Audio; -using System; -using System.Collections.Generic; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.Extensions; -using MediaBrowser.Model.Extensions; - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Class Genre - /// </summary> - public class Genre : BaseItem, IItemByName - { - public override List<string> GetUserDataKeys() - { - var list = base.GetUserDataKeys(); - - list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics()); - return list; - } - public override string CreatePresentationUniqueKey() - { - return GetUserDataKeys()[0]; - } - - public override double? GetDefaultPrimaryImageAspectRatio() - { - return 1; - } - - /// <summary> - /// Returns the folder containing the item. - /// If the item is a folder, it returns the folder itself - /// </summary> - /// <value>The containing folder path.</value> - [IgnoreDataMember] - public override string ContainingFolderPath - { - get - { - return Path; - } - } - - [IgnoreDataMember] - public override bool IsDisplayedAsFolder - { - get - { - return true; - } - } - - [IgnoreDataMember] - public override bool SupportsAncestors - { - get - { - return false; - } - } - - public override bool IsSaveLocalMetadataEnabled() - { - return true; - } - - public override bool CanDelete() - { - return false; - } - - /// <summary> - /// Gets a value indicating whether this instance is owned item. - /// </summary> - /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public override bool IsOwnedItem - { - get - { - return false; - } - } - - public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query) - { - query.GenreIds = new[] { Id.ToString("N") }; - query.ExcludeItemTypes = new[] { typeof(Game).Name, typeof(MusicVideo).Name, typeof(Audio.Audio).Name, typeof(MusicAlbum).Name, typeof(MusicArtist).Name }; - - return LibraryManager.GetItemList(query); - } - - [IgnoreDataMember] - public override bool SupportsPeople - { - get - { - return false; - } - } - - public static string GetPath(string name) - { - return GetPath(name, true); - } - - public static string GetPath(string name, bool normalizeName) - { - // Trim the period at the end because windows will have a hard time with that - var validName = normalizeName ? - FileSystem.GetValidFilename(name).Trim().TrimEnd('.') : - name; - - return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.GenrePath, validName); - } - - private string GetRebasedPath() - { - return GetPath(System.IO.Path.GetFileName(Path), false); - } - - public override bool RequiresRefresh() - { - var newPath = GetRebasedPath(); - if (!string.Equals(Path, newPath, StringComparison.Ordinal)) - { - Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath); - return true; - } - return base.RequiresRefresh(); - } - - /// <summary> - /// This is called before any metadata refresh and returns true or false indicating if changes were made - /// </summary> - public override bool BeforeMetadataRefresh() - { - var hasChanges = base.BeforeMetadataRefresh(); - - var newPath = GetRebasedPath(); - if (!string.Equals(Path, newPath, StringComparison.Ordinal)) - { - Path = newPath; - hasChanges = true; - } - - return hasChanges; - } - } -} diff --git a/MediaBrowser.Controller/Entities/ICollectionFolder.cs b/MediaBrowser.Controller/Entities/ICollectionFolder.cs deleted file mode 100644 index b70ad322d9..0000000000 --- a/MediaBrowser.Controller/Entities/ICollectionFolder.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// This is just a marker interface to denote top level folders - /// </summary> - public interface ICollectionFolder - { - string CollectionType { get; } - string Path { get; } - string Name { get; } - Guid Id { get; } - string[] PhysicalLocations { get; } - } - - public interface ISupportsUserSpecificView - { - bool EnableUserSpecificView { get; } - } -} diff --git a/MediaBrowser.Controller/Entities/IHasAspectRatio.cs b/MediaBrowser.Controller/Entities/IHasAspectRatio.cs deleted file mode 100644 index 5aecf4eac1..0000000000 --- a/MediaBrowser.Controller/Entities/IHasAspectRatio.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Interface IHasAspectRatio - /// </summary> - public interface IHasAspectRatio - { - /// <summary> - /// Gets or sets the aspect ratio. - /// </summary> - /// <value>The aspect ratio.</value> - string AspectRatio { get; set; } - } -} diff --git a/MediaBrowser.Controller/Entities/IHasDisplayOrder.cs b/MediaBrowser.Controller/Entities/IHasDisplayOrder.cs deleted file mode 100644 index 5e1ae21798..0000000000 --- a/MediaBrowser.Controller/Entities/IHasDisplayOrder.cs +++ /dev/null @@ -1,15 +0,0 @@ - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Interface IHasDisplayOrder - /// </summary> - public interface IHasDisplayOrder - { - /// <summary> - /// Gets or sets the display order. - /// </summary> - /// <value>The display order.</value> - string DisplayOrder { get; set; } - } -} diff --git a/MediaBrowser.Controller/Entities/IHasMediaSources.cs b/MediaBrowser.Controller/Entities/IHasMediaSources.cs deleted file mode 100644 index 54786134f3..0000000000 --- a/MediaBrowser.Controller/Entities/IHasMediaSources.cs +++ /dev/null @@ -1,17 +0,0 @@ -using MediaBrowser.Model.Dto; -using System.Collections.Generic; -using MediaBrowser.Model.Entities; - -namespace MediaBrowser.Controller.Entities -{ - public interface IHasMediaSources : IHasMetadata - { - /// <summary> - /// Gets the media sources. - /// </summary> - /// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param> - /// <returns>Task{IEnumerable{MediaSourceInfo}}.</returns> - List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution); - List<MediaStream> GetMediaStreams(); - } -} diff --git a/MediaBrowser.Controller/Entities/IHasMetadata.cs b/MediaBrowser.Controller/Entities/IHasMetadata.cs deleted file mode 100644 index b7d31b4d6a..0000000000 --- a/MediaBrowser.Controller/Entities/IHasMetadata.cs +++ /dev/null @@ -1,317 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Interface IHasMetadata - /// </summary> - public interface IHasMetadata : IHasProviderIds, IHasUserData - { - /// <summary> - /// Gets the preferred metadata country code. - /// </summary> - /// <returns>System.String.</returns> - string GetPreferredMetadataCountryCode(); - - /// <summary> - /// Gets the date modified. - /// </summary> - /// <value>The date modified.</value> - DateTime DateModified { get; set; } - - /// <summary> - /// Gets or sets the date last saved. - /// </summary> - /// <value>The date last saved.</value> - DateTime DateLastSaved { get; set; } - - SourceType SourceType { get; } - - /// <summary> - /// Gets or sets the date last refreshed. - /// </summary> - /// <value>The date last refreshed.</value> - DateTime DateLastRefreshed { get; set; } - - /// <summary> - /// This is called before any metadata refresh and returns true or false indicating if changes were made - /// </summary> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> - bool BeforeMetadataRefresh(); - - /// <summary> - /// Afters the metadata refresh. - /// </summary> - void AfterMetadataRefresh(); - - /// <summary> - /// Gets a value indicating whether [supports people]. - /// </summary> - /// <value><c>true</c> if [supports people]; otherwise, <c>false</c>.</value> - bool SupportsPeople { get; } - - bool RequiresRefresh(); - - bool EnableRefreshOnDateModifiedChange { get; } - - string PresentationUniqueKey { get; set; } - - string GetPresentationUniqueKey(); - string CreatePresentationUniqueKey(); - bool StopRefreshIfLocalMetadataFound { get; } - - int? GetInheritedParentalRatingValue(); - int InheritedParentalRatingValue { get; set; } - List<string> GetInheritedTags(); - long? RunTimeTicks { get; set; } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - string Name { get; set; } - - /// <summary> - /// Gets the path. - /// </summary> - /// <value>The path.</value> - string Path { get; set; } - - /// <summary> - /// Gets the file name without extension. - /// </summary> - /// <value>The file name without extension.</value> - string FileNameWithoutExtension { get; } - - /// <summary> - /// Gets the type of the location. - /// </summary> - /// <value>The type of the location.</value> - LocationType LocationType { get; } - - /// <summary> - /// Gets the locked fields. - /// </summary> - /// <value>The locked fields.</value> - MetadataFields[] LockedFields { get; } - - /// <summary> - /// Gets the images. - /// </summary> - /// <param name="imageType">Type of the image.</param> - /// <returns>IEnumerable{ItemImageInfo}.</returns> - IEnumerable<ItemImageInfo> GetImages(ImageType imageType); - - /// <summary> - /// Gets the image path. - /// </summary> - /// <param name="imageType">Type of the image.</param> - /// <param name="imageIndex">Index of the image.</param> - /// <returns>System.String.</returns> - string GetImagePath(ImageType imageType, int imageIndex); - - /// <summary> - /// Gets the image information. - /// </summary> - /// <param name="imageType">Type of the image.</param> - /// <param name="imageIndex">Index of the image.</param> - /// <returns>ItemImageInfo.</returns> - ItemImageInfo GetImageInfo(ImageType imageType, int imageIndex); - - /// <summary> - /// Sets the image. - /// </summary> - /// <param name="type">The type.</param> - /// <param name="index">The index.</param> - /// <param name="file">The file.</param> - void SetImagePath(ImageType type, int index, FileSystemMetadata file); - - /// <summary> - /// Determines whether the specified type has image. - /// </summary> - /// <param name="type">The type.</param> - /// <param name="imageIndex">Index of the image.</param> - /// <returns><c>true</c> if the specified type has image; otherwise, <c>false</c>.</returns> - bool HasImage(ImageType type, int imageIndex); - - /// <summary> - /// Allowses the multiple images. - /// </summary> - /// <param name="type">The type.</param> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> - bool AllowsMultipleImages(ImageType type); - - /// <summary> - /// Swaps the images. - /// </summary> - void SwapImages(ImageType type, int index1, int index2); - - /// <summary> - /// Gets or sets the primary image path. - /// </summary> - /// <value>The primary image path.</value> - string PrimaryImagePath { get; } - - /// <summary> - /// Gets the preferred metadata language. - /// </summary> - /// <returns>System.String.</returns> - string GetPreferredMetadataLanguage(); - - /// <summary> - /// Validates the images and returns true or false indicating if any were removed. - /// </summary> - bool ValidateImages(IDirectoryService directoryService); - - /// <summary> - /// Gets a value indicating whether this instance is owned item. - /// </summary> - /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> - bool IsOwnedItem { get; } - - /// <summary> - /// Gets the containing folder path. - /// </summary> - /// <value>The containing folder path.</value> - string ContainingFolderPath { get; } - - /// <summary> - /// Adds the images. - /// </summary> - /// <param name="imageType">Type of the image.</param> - /// <param name="images">The images.</param> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> - bool AddImages(ImageType imageType, List<FileSystemMetadata> images); - - /// <summary> - /// Determines whether [is save local metadata enabled]. - /// </summary> - /// <returns><c>true</c> if [is save local metadata enabled]; otherwise, <c>false</c>.</returns> - bool IsSaveLocalMetadataEnabled(); - - /// <summary> - /// Gets a value indicating whether [supports local metadata]. - /// </summary> - /// <value><c>true</c> if [supports local metadata]; otherwise, <c>false</c>.</value> - bool SupportsLocalMetadata { get; } - - bool IsInMixedFolder { get; } - - /// <summary> - /// Gets a value indicating whether this instance is locked. - /// </summary> - /// <value><c>true</c> if this instance is locked; otherwise, <c>false</c>.</value> - bool IsLocked { get; } - - /// <summary> - /// Gets a value indicating whether [supports remote image downloading]. - /// </summary> - /// <value><c>true</c> if [supports remote image downloading]; otherwise, <c>false</c>.</value> - bool SupportsRemoteImageDownloading { get; } - - /// <summary> - /// Gets the internal metadata path. - /// </summary> - /// <returns>System.String.</returns> - string GetInternalMetadataPath(); - - /// <summary> - /// Gets a value indicating whether [always scan internal metadata path]. - /// </summary> - /// <value><c>true</c> if [always scan internal metadata path]; otherwise, <c>false</c>.</value> - bool AlwaysScanInternalMetadataPath { get; } - - /// <summary> - /// Determines whether [is internet metadata enabled]. - /// </summary> - /// <returns><c>true</c> if [is internet metadata enabled]; otherwise, <c>false</c>.</returns> - bool IsInternetMetadataEnabled(); - - /// <summary> - /// Removes the image. - /// </summary> - /// <param name="image">The image.</param> - void RemoveImage(ItemImageInfo image); - - void RemoveImages(List<ItemImageInfo> images); - - /// <summary> - /// Updates to repository. - /// </summary> - void UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken); - - /// <summary> - /// Sets the image. - /// </summary> - /// <param name="image">The image.</param> - /// <param name="index">The index.</param> - void SetImage(ItemImageInfo image, int index); - - double? GetDefaultPrimaryImageAspectRatio(); - - int? ProductionYear { get; set; } - - string[] Tags { get; set; } - - ItemUpdateType OnMetadataChanged(); - } - - public static class HasMetadataExtensions - { - /// <summary> - /// Gets the image path. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="imageType">Type of the image.</param> - /// <returns>System.String.</returns> - public static string GetImagePath(this IHasMetadata item, ImageType imageType) - { - return item.GetImagePath(imageType, 0); - } - - public static bool HasImage(this IHasMetadata item, ImageType imageType) - { - return item.HasImage(imageType, 0); - } - - /// <summary> - /// Sets the image path. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="imageType">Type of the image.</param> - /// <param name="file">The file.</param> - public static void SetImagePath(this IHasMetadata item, ImageType imageType, FileSystemMetadata file) - { - item.SetImagePath(imageType, 0, file); - } - - /// <summary> - /// Sets the image path. - /// </summary> - /// <param name="item">The item.</param> - /// <param name="imageType">Type of the image.</param> - /// <param name="file">The file.</param> - public static void SetImagePath(this IHasMetadata item, ImageType imageType, string file) - { - if (file.StartsWith("http", System.StringComparison.OrdinalIgnoreCase)) - { - item.SetImage(new ItemImageInfo - { - Path = file, - Type = imageType - }, 0); - } - else - { - item.SetImagePath(imageType, BaseItem.FileSystem.GetFileInfo(file)); - } - } - } -} diff --git a/MediaBrowser.Controller/Entities/IHasProgramAttributes.cs b/MediaBrowser.Controller/Entities/IHasProgramAttributes.cs deleted file mode 100644 index 90786d44d7..0000000000 --- a/MediaBrowser.Controller/Entities/IHasProgramAttributes.cs +++ /dev/null @@ -1,20 +0,0 @@ -using MediaBrowser.Model.LiveTv; - -namespace MediaBrowser.Controller.Entities -{ - public interface IHasProgramAttributes - { - bool IsMovie { get; set; } - bool IsSports { get; set; } - bool IsNews { get; set; } - bool IsKids { get; set; } - bool IsRepeat { get; set; } - bool? IsHD { get; set; } - bool IsSeries { get; set; } - bool IsLive { get; set; } - bool IsPremiere { get; set; } - ProgramAudio? Audio { get; set; } - string EpisodeTitle { get; set; } - string ServiceName { get; set; } - } -} diff --git a/MediaBrowser.Controller/Entities/IHasScreenshots.cs b/MediaBrowser.Controller/Entities/IHasScreenshots.cs deleted file mode 100644 index 2fd402bc2b..0000000000 --- a/MediaBrowser.Controller/Entities/IHasScreenshots.cs +++ /dev/null @@ -1,10 +0,0 @@ - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Interface IHasScreenshots - /// </summary> - public interface IHasScreenshots - { - } -} diff --git a/MediaBrowser.Controller/Entities/IHasSeries.cs b/MediaBrowser.Controller/Entities/IHasSeries.cs deleted file mode 100644 index 20efdc2b8b..0000000000 --- a/MediaBrowser.Controller/Entities/IHasSeries.cs +++ /dev/null @@ -1,20 +0,0 @@ - -using System; - -namespace MediaBrowser.Controller.Entities -{ - public interface IHasSeries - { - /// <summary> - /// Gets the name of the series. - /// </summary> - /// <value>The name of the series.</value> - string SeriesName { get; set; } - string FindSeriesName(); - string FindSeriesSortName(); - Guid? SeriesId { get; set; } - Guid? FindSeriesId(); - string SeriesPresentationUniqueKey { get; set; } - string FindSeriesPresentationUniqueKey(); - } -} diff --git a/MediaBrowser.Controller/Entities/IHasSpecialFeatures.cs b/MediaBrowser.Controller/Entities/IHasSpecialFeatures.cs deleted file mode 100644 index f4905b7dcf..0000000000 --- a/MediaBrowser.Controller/Entities/IHasSpecialFeatures.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; - -namespace MediaBrowser.Controller.Entities -{ - public interface IHasSpecialFeatures - { - /// <summary> - /// Gets or sets the special feature ids. - /// </summary> - /// <value>The special feature ids.</value> - Guid[] SpecialFeatureIds { get; set; } - } -} diff --git a/MediaBrowser.Controller/Entities/IHasStartDate.cs b/MediaBrowser.Controller/Entities/IHasStartDate.cs deleted file mode 100644 index a6714fb964..0000000000 --- a/MediaBrowser.Controller/Entities/IHasStartDate.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System; - -namespace MediaBrowser.Controller.Entities -{ - public interface IHasStartDate - { - DateTime StartDate { get; set; } - } -} diff --git a/MediaBrowser.Controller/Entities/IHasTrailers.cs b/MediaBrowser.Controller/Entities/IHasTrailers.cs deleted file mode 100644 index 07dde37894..0000000000 --- a/MediaBrowser.Controller/Entities/IHasTrailers.cs +++ /dev/null @@ -1,38 +0,0 @@ -using MediaBrowser.Model.Entities; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace MediaBrowser.Controller.Entities -{ - public interface IHasTrailers : IHasMetadata - { - /// <summary> - /// Gets or sets the remote trailers. - /// </summary> - /// <value>The remote trailers.</value> - MediaUrl[] RemoteTrailers { get; set; } - - /// <summary> - /// Gets or sets the local trailer ids. - /// </summary> - /// <value>The local trailer ids.</value> - Guid[] LocalTrailerIds { get; set; } - Guid[] RemoteTrailerIds { get; set; } - } - - public static class HasTrailerExtensions - { - /// <summary> - /// Gets the trailer ids. - /// </summary> - /// <returns>List<Guid>.</returns> - public static List<Guid> GetTrailerIds(this IHasTrailers item) - { - var list = item.LocalTrailerIds.ToList(); - list.AddRange(item.RemoteTrailerIds); - return list; - } - - } -} diff --git a/MediaBrowser.Controller/Entities/IHasUserData.cs b/MediaBrowser.Controller/Entities/IHasUserData.cs deleted file mode 100644 index ab4f624e21..0000000000 --- a/MediaBrowser.Controller/Entities/IHasUserData.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Querying; - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Interface IHasUserData - /// </summary> - public interface IHasUserData - { - List<string> GetUserDataKeys(); - - /// <summary> - /// Fills the user data dto values. - /// </summary> - void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user, ItemFields[] fields); - - bool EnableRememberingTrackSelections { get; } - - bool SupportsPlayedStatus { get; } - - Guid Id { get; } - } -} diff --git a/MediaBrowser.Controller/Entities/IHiddenFromDisplay.cs b/MediaBrowser.Controller/Entities/IHiddenFromDisplay.cs deleted file mode 100644 index ba6311296a..0000000000 --- a/MediaBrowser.Controller/Entities/IHiddenFromDisplay.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace MediaBrowser.Controller.Entities -{ - public interface IHiddenFromDisplay - { - /// <summary> - /// Determines whether the specified user is hidden. - /// </summary> - /// <param name="user">The user.</param> - /// <returns><c>true</c> if the specified user is hidden; otherwise, <c>false</c>.</returns> - bool IsHiddenFromUser(User user); - } -} diff --git a/MediaBrowser.Controller/Entities/IItemByName.cs b/MediaBrowser.Controller/Entities/IItemByName.cs deleted file mode 100644 index a02ca1c0c4..0000000000 --- a/MediaBrowser.Controller/Entities/IItemByName.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System.Collections.Generic; - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Marker interface - /// </summary> - public interface IItemByName : IHasMetadata - { - IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query); - } - - public interface IHasDualAccess : IItemByName - { - bool IsAccessedByName { get; } - } -} diff --git a/MediaBrowser.Controller/Entities/IMetadataContainer.cs b/MediaBrowser.Controller/Entities/IMetadataContainer.cs deleted file mode 100644 index 33aa08425d..0000000000 --- a/MediaBrowser.Controller/Entities/IMetadataContainer.cs +++ /dev/null @@ -1,19 +0,0 @@ -using MediaBrowser.Controller.Providers; -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Controller.Entities -{ - public interface IMetadataContainer - { - /// <summary> - /// Refreshes all metadata. - /// </summary> - /// <param name="refreshOptions">The refresh options.</param> - /// <param name="progress">The progress.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken); - } -} diff --git a/MediaBrowser.Controller/Entities/ISupportsBoxSetGrouping.cs b/MediaBrowser.Controller/Entities/ISupportsBoxSetGrouping.cs deleted file mode 100644 index fbe5a06d0e..0000000000 --- a/MediaBrowser.Controller/Entities/ISupportsBoxSetGrouping.cs +++ /dev/null @@ -1,12 +0,0 @@ - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Marker interface to denote a class that supports being hidden underneath it's boxset. - /// Just about anything can be placed into a boxset, - /// but movies should also only appear underneath and not outside separately (subject to configuration). - /// </summary> - public interface ISupportsBoxSetGrouping - { - } -} diff --git a/MediaBrowser.Controller/Entities/ISupportsPlaceHolders.cs b/MediaBrowser.Controller/Entities/ISupportsPlaceHolders.cs deleted file mode 100644 index 2507c8ee65..0000000000 --- a/MediaBrowser.Controller/Entities/ISupportsPlaceHolders.cs +++ /dev/null @@ -1,12 +0,0 @@ - -namespace MediaBrowser.Controller.Entities -{ - public interface ISupportsPlaceHolders - { - /// <summary> - /// Gets a value indicating whether this instance is place holder. - /// </summary> - /// <value><c>true</c> if this instance is place holder; otherwise, <c>false</c>.</value> - bool IsPlaceHolder { get; } - } -} diff --git a/MediaBrowser.Controller/Entities/IVirtualFolderCreator.cs b/MediaBrowser.Controller/Entities/IVirtualFolderCreator.cs deleted file mode 100644 index 57e9e8d5d9..0000000000 --- a/MediaBrowser.Controller/Entities/IVirtualFolderCreator.cs +++ /dev/null @@ -1,15 +0,0 @@ - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Interface IVirtualFolderCreator - /// </summary> - public interface IVirtualFolderCreator - { - /// <summary> - /// Gets the folder. - /// </summary> - /// <returns>Folder.</returns> - BasePluginFolder GetFolder(); - } -} diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs deleted file mode 100644 index a7f6c60148..0000000000 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ /dev/null @@ -1,243 +0,0 @@ -using MediaBrowser.Model.Entities; -using System; -using System.Collections.Generic; -using MediaBrowser.Model.Configuration; -using System.Linq; -using MediaBrowser.Controller.Dto; -using MediaBrowser.Model.Querying; - -namespace MediaBrowser.Controller.Entities -{ - public class InternalItemsQuery - { - public bool Recursive { get; set; } - - public int? StartIndex { get; set; } - - public int? Limit { get; set; } - - public User User { get; set; } - - public BaseItem SimilarTo { get; set; } - - public bool? IsFolder { get; set; } - public bool? IsFavorite { get; set; } - public bool? IsFavoriteOrLiked { get; set; } - public bool? IsLiked { get; set; } - public bool? IsPlayed { get; set; } - public bool? IsResumable { get; set; } - public bool? IncludeItemsByName { get; set; } - - public string[] MediaTypes { get; set; } - public string[] IncludeItemTypes { get; set; } - public string[] ExcludeItemTypes { get; set; } - public string[] ExcludeTags { get; set; } - public string[] ExcludeInheritedTags { get; set; } - public string[] Genres { get; set; } - - public bool? IsSpecialSeason { get; set; } - public bool? IsMissing { get; set; } - public bool? IsUnaired { get; set; } - public bool? CollapseBoxSetItems { get; set; } - - public string NameStartsWithOrGreater { get; set; } - public string NameStartsWith { get; set; } - public string NameLessThan { get; set; } - public string NameContains { get; set; } - public string MinSortName { get; set; } - - public string PresentationUniqueKey { get; set; } - public string Path { get; set; } - public string PathNotStartsWith { get; set; } - public string Name { get; set; } - - public string Person { get; set; } - public string[] PersonIds { get; set; } - public string[] ItemIds { get; set; } - public string[] ExcludeItemIds { get; set; } - public string AdjacentTo { get; set; } - public string[] PersonTypes { get; set; } - - public bool? Is3D { get; set; } - public bool? IsHD { get; set; } - public bool? IsInBoxSet { get; set; } - public bool? IsLocked { get; set; } - public bool? IsPlaceHolder { get; set; } - - public bool? HasImdbId { get; set; } - public bool? HasOverview { get; set; } - public bool? HasTmdbId { get; set; } - public bool? HasOfficialRating { get; set; } - public bool? HasTvdbId { get; set; } - public bool? HasThemeSong { get; set; } - public bool? HasThemeVideo { get; set; } - public bool? HasSubtitles { get; set; } - public bool? HasSpecialFeature { get; set; } - public bool? HasTrailer { get; set; } - public bool? HasParentalRating { get; set; } - - public string[] StudioIds { get; set; } - public string[] GenreIds { get; set; } - public ImageType[] ImageTypes { get; set; } - public VideoType[] VideoTypes { get; set; } - public UnratedItem[] BlockUnratedItems { get; set; } - public int[] Years { get; set; } - public string[] Tags { get; set; } - public string[] OfficialRatings { get; set; } - - public DateTime? MinPremiereDate { get; set; } - public DateTime? MaxPremiereDate { get; set; } - public DateTime? MinStartDate { get; set; } - public DateTime? MaxStartDate { get; set; } - public DateTime? MinEndDate { get; set; } - public DateTime? MaxEndDate { get; set; } - public bool? IsAiring { get; set; } - - public bool? IsMovie { get; set; } - public bool? IsSports { get; set; } - public bool? IsKids { get; set; } - public bool? IsNews { get; set; } - public bool? IsSeries { get; set; } - - public int? MinPlayers { get; set; } - public int? MaxPlayers { get; set; } - public int? MinIndexNumber { get; set; } - public int? AiredDuringSeason { get; set; } - public double? MinCriticRating { get; set; } - public double? MinCommunityRating { get; set; } - - public string[] ChannelIds { get; set; } - - internal List<Guid> ItemIdsFromPersonFilters { get; set; } - public int? ParentIndexNumber { get; set; } - public int? ParentIndexNumberNotEquals { get; set; } - public int? IndexNumber { get; set; } - public int? MinParentalRating { get; set; } - public int? MaxParentalRating { get; set; } - - public bool? HasDeadParentId { get; set; } - public bool? IsVirtualItem { get; set; } - - public Guid? ParentId { get; set; } - public string ParentType { get; set; } - public string[] AncestorIds { get; set; } - public string[] TopParentIds { get; set; } - - public BaseItem Parent - { - set - { - if (value == null) - { - ParentId = null; - ParentType = null; - } - else - { - ParentId = value.Id; - ParentType = value.GetType().Name; - } - } - } - - public string[] PresetViews { get; set; } - public TrailerType[] TrailerTypes { get; set; } - public SourceType[] SourceTypes { get; set; } - - public SeriesStatus[] SeriesStatuses { get; set; } - public string ExternalSeriesId { get; set; } - public string ExternalId { get; set; } - - public string[] AlbumIds { get; set; } - public string[] ArtistIds { get; set; } - public string[] ExcludeArtistIds { get; set; } - public string AncestorWithPresentationUniqueKey { get; set; } - public string SeriesPresentationUniqueKey { get; set; } - - public bool GroupByPresentationUniqueKey { get; set; } - public bool GroupBySeriesPresentationUniqueKey { get; set; } - public bool EnableTotalRecordCount { get; set; } - public bool ForceDirect { get; set; } - public Dictionary<string, string> ExcludeProviderIds { get; set; } - public bool EnableGroupByMetadataKey { get; set; } - public bool? HasChapterImages { get; set; } - - public Tuple<string, SortOrder>[] OrderBy { get; set; } - - public DateTime? MinDateCreated { get; set; } - public DateTime? MinDateLastSaved { get; set; } - public DateTime? MinDateLastSavedForUser { get; set; } - - public DtoOptions DtoOptions { get; set; } - public int MinSimilarityScore { get; set; } - public string HasNoAudioTrackWithLanguage { get; set; } - public string HasNoInternalSubtitleTrackWithLanguage { get; set; } - public string HasNoExternalSubtitleTrackWithLanguage { get; set; } - public string HasNoSubtitleTrackWithLanguage { get; set; } - - public InternalItemsQuery() - { - MinSimilarityScore = 20; - - GroupByPresentationUniqueKey = true; - EnableTotalRecordCount = true; - - DtoOptions = new DtoOptions(); - AlbumIds = new string[] { }; - ArtistIds = new string[] { }; - ExcludeArtistIds = new string[] { }; - ExcludeProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - - BlockUnratedItems = new UnratedItem[] { }; - Tags = new string[] { }; - OfficialRatings = new string[] { }; - MediaTypes = new string[] { }; - IncludeItemTypes = new string[] { }; - ExcludeItemTypes = new string[] { }; - Genres = new string[] { }; - StudioIds = new string[] { }; - GenreIds = new string[] { }; - ImageTypes = new ImageType[] { }; - VideoTypes = new VideoType[] { }; - Years = new int[] { }; - PersonTypes = new string[] { }; - PersonIds = new string[] { }; - ChannelIds = new string[] { }; - ItemIds = new string[] { }; - ExcludeItemIds = new string[] { }; - AncestorIds = new string[] { }; - TopParentIds = new string[] { }; - ExcludeTags = new string[] { }; - ExcludeInheritedTags = new string[] { }; - PresetViews = new string[] { }; - TrailerTypes = new TrailerType[] { }; - SourceTypes = new SourceType[] { }; - SeriesStatuses = new SeriesStatus[] { }; - OrderBy = new Tuple<string, SortOrder>[] { }; - } - - public InternalItemsQuery(User user) - : this() - { - SetUser(user); - } - - public void SetUser(User user) - { - if (user != null) - { - var policy = user.Policy; - MaxParentalRating = policy.MaxParentalRating; - - if (policy.MaxParentalRating.HasValue) - { - BlockUnratedItems = policy.BlockUnratedItems.Where(i => i != UnratedItem.Other).ToArray(); - } - - ExcludeInheritedTags = policy.BlockedTags; - - User = user; - } - } - } -} diff --git a/MediaBrowser.Controller/Entities/InternalPeopleQuery.cs b/MediaBrowser.Controller/Entities/InternalPeopleQuery.cs deleted file mode 100644 index 9e0e9c2088..0000000000 --- a/MediaBrowser.Controller/Entities/InternalPeopleQuery.cs +++ /dev/null @@ -1,21 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace MediaBrowser.Controller.Entities -{ - public class InternalPeopleQuery - { - public Guid ItemId { get; set; } - public string[] PersonTypes { get; set; } - public List<string> ExcludePersonTypes { get; set; } - public int? MaxListOrder { get; set; } - public Guid AppearsInItemId { get; set; } - public string NameContains { get; set; } - - public InternalPeopleQuery() - { - PersonTypes = new string[] {}; - ExcludePersonTypes = new List<string>(); - } - } -} diff --git a/MediaBrowser.Controller/Entities/ItemImageInfo.cs b/MediaBrowser.Controller/Entities/ItemImageInfo.cs deleted file mode 100644 index bd0011c4b3..0000000000 --- a/MediaBrowser.Controller/Entities/ItemImageInfo.cs +++ /dev/null @@ -1,46 +0,0 @@ -using MediaBrowser.Model.Entities; -using System; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Controller.Entities -{ - public class ItemImageInfo - { - /// <summary> - /// Gets or sets the path. - /// </summary> - /// <value>The path.</value> - public string Path { get; set; } - - /// <summary> - /// Gets or sets the type. - /// </summary> - /// <value>The type.</value> - public ImageType Type { get; set; } - - /// <summary> - /// Gets or sets the date modified. - /// </summary> - /// <value>The date modified.</value> - public DateTime DateModified { get; set; } - - public int Width { get; set; } - public int Height { get; set; } - - [IgnoreDataMember] - public bool IsLocalFile - { - get - { - if (Path != null) - { - if (Path.StartsWith("http", StringComparison.OrdinalIgnoreCase)) - { - return false; - } - } - return true; - } - } - } -} diff --git a/MediaBrowser.Controller/Entities/LinkedChild.cs b/MediaBrowser.Controller/Entities/LinkedChild.cs deleted file mode 100644 index 6031a2448a..0000000000 --- a/MediaBrowser.Controller/Entities/LinkedChild.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System; -using System.Collections.Generic; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Controller.Entities -{ - public class LinkedChild - { - public string Path { get; set; } - public LinkedChildType Type { get; set; } - - [IgnoreDataMember] - public string Id { get; set; } - - /// <summary> - /// Serves as a cache - /// </summary> - public Guid? ItemId { get; set; } - - public static LinkedChild Create(BaseItem item) - { - return new LinkedChild - { - Path = item.Path, - Type = LinkedChildType.Manual - }; - } - - public LinkedChild() - { - Id = Guid.NewGuid().ToString("N"); - } - } - - public enum LinkedChildType - { - Manual = 0, - Shortcut = 1 - } - - public class LinkedChildComparer : IEqualityComparer<LinkedChild> - { - private readonly IFileSystem _fileSystem; - - public LinkedChildComparer(IFileSystem fileSystem) - { - _fileSystem = fileSystem; - } - - public bool Equals(LinkedChild x, LinkedChild y) - { - if (x.Type == y.Type) - { - return _fileSystem.AreEqual(x.Path, y.Path); - } - return false; - } - - public int GetHashCode(LinkedChild obj) - { - return (obj.Path + obj.Type).GetHashCode(); - } - } -} diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs deleted file mode 100644 index 268860ff01..0000000000 --- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs +++ /dev/null @@ -1,216 +0,0 @@ -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Querying; -using MediaBrowser.Model.Users; -using System; -using System.Collections.Generic; -using System.Linq; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Controller.Entities.Movies -{ - /// <summary> - /// Class BoxSet - /// </summary> - public class BoxSet : Folder, IHasTrailers, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IHasShares - { - public List<Share> Shares { get; set; } - - public BoxSet() - { - RemoteTrailers = EmptyMediaUrlArray; - LocalTrailerIds = EmptyGuidArray; - RemoteTrailerIds = EmptyGuidArray; - - DisplayOrder = ItemSortBy.PremiereDate; - Shares = new List<Share>(); - } - - [IgnoreDataMember] - protected override bool FilterLinkedChildrenPerUser - { - get - { - return true; - } - } - - [IgnoreDataMember] - public override bool SupportsInheritedParentImages - { - get - { - return false; - } - } - - [IgnoreDataMember] - public override bool SupportsPeople - { - get { return true; } - } - - public Guid[] LocalTrailerIds { get; set; } - public Guid[] RemoteTrailerIds { get; set; } - - /// <summary> - /// Gets or sets the remote trailers. - /// </summary> - /// <value>The remote trailers.</value> - public MediaUrl[] RemoteTrailers { get; set; } - - /// <summary> - /// Gets or sets the display order. - /// </summary> - /// <value>The display order.</value> - public string DisplayOrder { get; set; } - - protected override bool GetBlockUnratedValue(UserPolicy config) - { - return config.BlockUnratedItems.Contains(UnratedItem.Movie); - } - - public override double? GetDefaultPrimaryImageAspectRatio() - { - double value = 2; - value /= 3; - - return value; - } - - public override UnratedItem GetBlockUnratedType() - { - return UnratedItem.Movie; - } - - protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService) - { - if (IsLegacyBoxSet) - { - return base.GetNonCachedChildren(directoryService); - } - return new List<BaseItem>(); - } - - protected override List<BaseItem> LoadChildren() - { - if (IsLegacyBoxSet) - { - return base.LoadChildren(); - } - - // Save a trip to the database - return new List<BaseItem>(); - } - - [IgnoreDataMember] - private bool IsLegacyBoxSet - { - get - { - if (string.IsNullOrWhiteSpace(Path)) - { - return false; - } - - if (LinkedChildren.Length > 0) - { - return false; - } - - return !FileSystem.ContainsSubPath(ConfigurationManager.ApplicationPaths.DataPath, Path); - } - } - - [IgnoreDataMember] - public override bool IsPreSorted - { - get - { - return true; - } - } - - public override bool IsAuthorizedToDelete(User user, List<Folder> allCollectionFolders) - { - return true; - } - - public override bool IsSaveLocalMetadataEnabled() - { - return true; - } - - /// <summary> - /// Updates the official rating based on content and returns true or false indicating if it changed. - /// </summary> - /// <returns></returns> - public bool UpdateRatingToContent() - { - var currentOfficialRating = OfficialRating; - - // Gather all possible ratings - var ratings = GetLinkedChildren() - .Select(i => i.OfficialRating) - .Where(i => !string.IsNullOrEmpty(i)) - .Distinct(StringComparer.OrdinalIgnoreCase) - .Select(i => new Tuple<string, int?>(i, LocalizationManager.GetRatingLevel(i))) - .OrderBy(i => i.Item2 ?? 1000) - .Select(i => i.Item1); - - OfficialRating = ratings.FirstOrDefault() ?? currentOfficialRating; - - return !string.Equals(currentOfficialRating ?? string.Empty, OfficialRating ?? string.Empty, - StringComparison.OrdinalIgnoreCase); - } - - public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren) - { - var children = base.GetChildren(user, includeLinkedChildren); - - if (string.Equals(DisplayOrder, ItemSortBy.SortName, StringComparison.OrdinalIgnoreCase)) - { - // Sort by name - return LibraryManager.Sort(children, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending).ToList(); - } - - if (string.Equals(DisplayOrder, ItemSortBy.PremiereDate, StringComparison.OrdinalIgnoreCase)) - { - // Sort by release date - return LibraryManager.Sort(children, user, new[] { ItemSortBy.ProductionYear, ItemSortBy.PremiereDate, ItemSortBy.SortName }, SortOrder.Ascending).ToList(); - } - - // Default sorting - return LibraryManager.Sort(children, user, new[] { ItemSortBy.ProductionYear, ItemSortBy.PremiereDate, ItemSortBy.SortName }, SortOrder.Ascending).ToList(); - } - - public BoxSetInfo GetLookupInfo() - { - return GetItemLookupInfo<BoxSetInfo>(); - } - - public override bool IsVisible(User user) - { - var userId = user.Id.ToString("N"); - - // Need to check Count > 0 for boxsets created prior to the introduction of Shares - if (Shares.Count > 0 && Shares.Any(i => string.Equals(userId, i.UserId, StringComparison.OrdinalIgnoreCase))) - { - return true; - } - - if (base.IsVisible(user)) - { - return base.GetChildren(user, true).Count > 0; - } - - return false; - } - - public override bool IsVisibleStandalone(User user) - { - return IsVisible(user); - } - } -} diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs deleted file mode 100644 index 2e0e019443..0000000000 --- a/MediaBrowser.Controller/Entities/Movies/Movie.cs +++ /dev/null @@ -1,197 +0,0 @@ -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Entities; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -using MediaBrowser.Controller.IO; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Providers; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Controller.Entities.Movies -{ - /// <summary> - /// Class Movie - /// </summary> - public class Movie : Video, IHasSpecialFeatures, IHasTrailers, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping - { - public Guid[] SpecialFeatureIds { get; set; } - - public Movie() - { - SpecialFeatureIds = EmptyGuidArray; - RemoteTrailers = EmptyMediaUrlArray; - LocalTrailerIds = EmptyGuidArray; - RemoteTrailerIds = EmptyGuidArray; - } - - public Guid[] LocalTrailerIds { get; set; } - public Guid[] RemoteTrailerIds { get; set; } - - public MediaUrl[] RemoteTrailers { get; set; } - - /// <summary> - /// Gets or sets the name of the TMDB collection. - /// </summary> - /// <value>The name of the TMDB collection.</value> - public string TmdbCollectionName { get; set; } - - [IgnoreDataMember] - public string CollectionName - { - get { return TmdbCollectionName; } - set { TmdbCollectionName = value; } - } - - public override double? GetDefaultPrimaryImageAspectRatio() - { - double value = 2; - value /= 3; - - return value; - } - - protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) - { - var hasChanges = await base.RefreshedOwnedItems(options, fileSystemChildren, cancellationToken).ConfigureAwait(false); - - // Must have a parent to have special features - // In other words, it must be part of the Parent/Child tree - if (LocationType == LocationType.FileSystem && GetParent() != null && !IsInMixedFolder) - { - var specialFeaturesChanged = await RefreshSpecialFeatures(options, fileSystemChildren, cancellationToken).ConfigureAwait(false); - - if (specialFeaturesChanged) - { - hasChanges = true; - } - } - - return hasChanges; - } - - private async Task<bool> RefreshSpecialFeatures(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) - { - var newItems = LibraryManager.FindExtras(this, fileSystemChildren, options.DirectoryService).ToList(); - var newItemIds = newItems.Select(i => i.Id).ToArray(); - - var itemsChanged = !SpecialFeatureIds.SequenceEqual(newItemIds); - - 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); - - SpecialFeatureIds = newItemIds; - - return itemsChanged; - } - - public override UnratedItem GetBlockUnratedType() - { - return UnratedItem.Movie; - } - - public MovieInfo GetLookupInfo() - { - var info = GetItemLookupInfo<MovieInfo>(); - - if (!IsInMixedFolder) - { - var name = System.IO.Path.GetFileName(ContainingFolderPath); - - if (VideoType == VideoType.VideoFile || VideoType == VideoType.Iso) - { - if (string.Equals(name, System.IO.Path.GetFileName(Path), StringComparison.OrdinalIgnoreCase)) - { - // if the folder has the file extension, strip it - name = System.IO.Path.GetFileNameWithoutExtension(name); - } - } - - info.Name = name; - } - - return info; - } - - public override bool BeforeMetadataRefresh() - { - var hasChanges = base.BeforeMetadataRefresh(); - - if (!ProductionYear.HasValue) - { - var info = LibraryManager.ParseName(Name); - - var yearInName = info.Year; - - if (yearInName.HasValue) - { - ProductionYear = yearInName; - hasChanges = true; - } - else - { - // Try to get the year from the folder name - if (!IsInMixedFolder) - { - info = LibraryManager.ParseName(System.IO.Path.GetFileName(ContainingFolderPath)); - - yearInName = info.Year; - - if (yearInName.HasValue) - { - ProductionYear = yearInName; - hasChanges = true; - } - } - } - } - - return hasChanges; - } - - public override List<ExternalUrl> GetRelatedUrls() - { - var list = base.GetRelatedUrls(); - - var imdbId = this.GetProviderId(MetadataProviders.Imdb); - if (!string.IsNullOrWhiteSpace(imdbId)) - { - list.Add(new ExternalUrl - { - Name = "Trakt", - Url = string.Format("https://trakt.tv/movies/{0}", imdbId) - }); - } - - return list; - } - - [IgnoreDataMember] - public override bool StopRefreshIfLocalMetadataFound - { - get - { - // Need people id's from internet metadata - return false; - } - } - } -} diff --git a/MediaBrowser.Controller/Entities/MusicVideo.cs b/MediaBrowser.Controller/Entities/MusicVideo.cs deleted file mode 100644 index b7470d679d..0000000000 --- a/MediaBrowser.Controller/Entities/MusicVideo.cs +++ /dev/null @@ -1,74 +0,0 @@ -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Configuration; -using System.Collections.Generic; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Controller.Entities -{ - public class MusicVideo : Video, IHasArtist, IHasMusicGenres, IHasLookupInfo<MusicVideoInfo> - { - [IgnoreDataMember] - public string[] Artists { get; set; } - - public MusicVideo() - { - Artists = EmptyStringArray; - } - - [IgnoreDataMember] - public string[] AllArtists - { - get - { - return Artists; - } - } - - public override UnratedItem GetBlockUnratedType() - { - return UnratedItem.Music; - } - - public MusicVideoInfo GetLookupInfo() - { - return GetItemLookupInfo<MusicVideoInfo>(); - } - - public override bool BeforeMetadataRefresh() - { - var hasChanges = base.BeforeMetadataRefresh(); - - if (!ProductionYear.HasValue) - { - var info = LibraryManager.ParseName(Name); - - var yearInName = info.Year; - - if (yearInName.HasValue) - { - ProductionYear = yearInName; - hasChanges = true; - } - else - { - // Try to get the year from the folder name - if (!IsInMixedFolder) - { - info = LibraryManager.ParseName(System.IO.Path.GetFileName(ContainingFolderPath)); - - yearInName = info.Year; - - if (yearInName.HasValue) - { - ProductionYear = yearInName; - hasChanges = true; - } - } - } - } - - return hasChanges; - } - } -} diff --git a/MediaBrowser.Controller/Entities/PeopleHelper.cs b/MediaBrowser.Controller/Entities/PeopleHelper.cs deleted file mode 100644 index 412eb94998..0000000000 --- a/MediaBrowser.Controller/Entities/PeopleHelper.cs +++ /dev/null @@ -1,119 +0,0 @@ -using MediaBrowser.Model.Entities; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace MediaBrowser.Controller.Entities -{ - public static class PeopleHelper - { - public static void AddPerson(List<PersonInfo> people, PersonInfo person) - { - if (person == null) - { - throw new ArgumentNullException("person"); - } - - if (string.IsNullOrWhiteSpace(person.Name)) - { - throw new ArgumentNullException(); - } - - // Normalize - if (string.Equals(person.Role, PersonType.GuestStar, StringComparison.OrdinalIgnoreCase)) - { - person.Type = PersonType.GuestStar; - } - else if (string.Equals(person.Role, PersonType.Director, StringComparison.OrdinalIgnoreCase)) - { - person.Type = PersonType.Director; - } - else if (string.Equals(person.Role, PersonType.Producer, StringComparison.OrdinalIgnoreCase)) - { - person.Type = PersonType.Producer; - } - else if (string.Equals(person.Role, PersonType.Writer, StringComparison.OrdinalIgnoreCase)) - { - person.Type = PersonType.Writer; - } - - // If the type is GuestStar and there's already an Actor entry, then update it to avoid dupes - if (string.Equals(person.Type, PersonType.GuestStar, StringComparison.OrdinalIgnoreCase)) - { - var existing = people.FirstOrDefault(p => p.Name.Equals(person.Name, StringComparison.OrdinalIgnoreCase) && p.Type.Equals(PersonType.Actor, StringComparison.OrdinalIgnoreCase)); - - if (existing != null) - { - existing.Type = PersonType.GuestStar; - MergeExisting(existing, person); - return; - } - } - - if (string.Equals(person.Type, PersonType.Actor, StringComparison.OrdinalIgnoreCase)) - { - // If the actor already exists without a role and we have one, fill it in - var existing = people.FirstOrDefault(p => p.Name.Equals(person.Name, StringComparison.OrdinalIgnoreCase) && (p.Type.Equals(PersonType.Actor, StringComparison.OrdinalIgnoreCase) || p.Type.Equals(PersonType.GuestStar, StringComparison.OrdinalIgnoreCase))); - if (existing == null) - { - // Wasn't there - add it - people.Add(person); - } - else - { - // Was there, if no role and we have one - fill it in - if (string.IsNullOrWhiteSpace(existing.Role) && !string.IsNullOrWhiteSpace(person.Role)) - { - existing.Role = person.Role; - } - - MergeExisting(existing, person); - } - } - else - { - var existing = people.FirstOrDefault(p => - string.Equals(p.Name, person.Name, StringComparison.OrdinalIgnoreCase) && - string.Equals(p.Type, person.Type, StringComparison.OrdinalIgnoreCase)); - - // Check for dupes based on the combination of Name and Type - if (existing == null) - { - people.Add(person); - } - else - { - MergeExisting(existing, person); - } - } - } - - private static void MergeExisting(PersonInfo existing, PersonInfo person) - { - existing.SortOrder = person.SortOrder ?? existing.SortOrder; - existing.ImageUrl = person.ImageUrl ?? existing.ImageUrl; - - foreach (var id in person.ProviderIds) - { - existing.SetProviderId(id.Key, id.Value); - } - } - - public static bool ContainsPerson(List<PersonInfo> people, string name) - { - if (string.IsNullOrWhiteSpace(name)) - { - throw new ArgumentNullException("name"); - } - - foreach (var i in people) - { - if (string.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - } - return false; - } - } -} diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs deleted file mode 100644 index b3a91f9446..0000000000 --- a/MediaBrowser.Controller/Entities/Person.cs +++ /dev/null @@ -1,229 +0,0 @@ -using MediaBrowser.Controller.Providers; -using System; -using System.Collections.Generic; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.Extensions; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// This is the full Person object that can be retrieved with all of it's data. - /// </summary> - public class Person : BaseItem, IItemByName, IHasLookupInfo<PersonLookupInfo> - { - public override List<string> GetUserDataKeys() - { - var list = base.GetUserDataKeys(); - - list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics()); - return list; - } - public override string CreatePresentationUniqueKey() - { - return GetUserDataKeys()[0]; - } - - public PersonLookupInfo GetLookupInfo() - { - return GetItemLookupInfo<PersonLookupInfo>(); - } - - public override double? GetDefaultPrimaryImageAspectRatio() - { - double value = 2; - value /= 3; - - return value; - } - - public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query) - { - query.PersonIds = new[] { Id.ToString("N") }; - - return LibraryManager.GetItemList(query); - } - - /// <summary> - /// Returns the folder containing the item. - /// If the item is a folder, it returns the folder itself - /// </summary> - /// <value>The containing folder path.</value> - [IgnoreDataMember] - public override string ContainingFolderPath - { - get - { - return Path; - } - } - - public override bool CanDelete() - { - return false; - } - - public override bool IsSaveLocalMetadataEnabled() - { - return true; - } - - [IgnoreDataMember] - public override bool EnableAlphaNumericSorting - { - get - { - return false; - } - } - - /// <summary> - /// Gets a value indicating whether this instance is owned item. - /// </summary> - /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public override bool IsOwnedItem - { - get - { - return false; - } - } - - [IgnoreDataMember] - public override bool SupportsPeople - { - get - { - return false; - } - } - - [IgnoreDataMember] - public override bool SupportsAncestors - { - get - { - return false; - } - } - - public static string GetPath(string name) - { - return GetPath(name, true); - } - - public static string GetPath(string name, bool normalizeName) - { - // Trim the period at the end because windows will have a hard time with that - var validFilename = normalizeName ? - FileSystem.GetValidFilename(name).Trim().TrimEnd('.') : - name; - - string subFolderPrefix = null; - - foreach (char c in validFilename) - { - if (char.IsLetterOrDigit(c)) - { - subFolderPrefix = c.ToString(); - break; - } - } - - var path = ConfigurationManager.ApplicationPaths.PeoplePath; - - return string.IsNullOrEmpty(subFolderPrefix) ? - System.IO.Path.Combine(path, validFilename) : - System.IO.Path.Combine(path, subFolderPrefix, validFilename); - } - - private string GetRebasedPath() - { - return GetPath(System.IO.Path.GetFileName(Path), false); - } - - public override bool RequiresRefresh() - { - var newPath = GetRebasedPath(); - if (!string.Equals(Path, newPath, StringComparison.Ordinal)) - { - Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath); - return true; - } - return base.RequiresRefresh(); - } - - /// <summary> - /// This is called before any metadata refresh and returns true or false indicating if changes were made - /// </summary> - public override bool BeforeMetadataRefresh() - { - var hasChanges = base.BeforeMetadataRefresh(); - - var newPath = GetRebasedPath(); - if (!string.Equals(Path, newPath, StringComparison.Ordinal)) - { - Path = newPath; - hasChanges = true; - } - - return hasChanges; - } - } - - /// <summary> - /// This is the small Person stub that is attached to BaseItems - /// </summary> - public class PersonInfo : IHasProviderIds - { - public PersonInfo() - { - ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); - } - - public Guid ItemId { get; set; } - - /// <summary> - /// Gets or sets the name. - /// </summary> - /// <value>The name.</value> - public string Name { get; set; } - /// <summary> - /// Gets or sets the role. - /// </summary> - /// <value>The role.</value> - public string Role { get; set; } - /// <summary> - /// Gets or sets the type. - /// </summary> - /// <value>The type.</value> - public string Type { get; set; } - - /// <summary> - /// Gets or sets the sort order - ascending - /// </summary> - /// <value>The sort order.</value> - public int? SortOrder { get; set; } - - public string ImageUrl { get; set; } - - public Dictionary<string, string> ProviderIds { get; set; } - - /// <summary> - /// Returns a <see cref="System.String" /> that represents this instance. - /// </summary> - /// <returns>A <see cref="System.String" /> that represents this instance.</returns> - public override string ToString() - { - return Name; - } - - public bool IsType(string type) - { - return string.Equals(Type, type, StringComparison.OrdinalIgnoreCase) || string.Equals(Role, type, StringComparison.OrdinalIgnoreCase); - } - } -} diff --git a/MediaBrowser.Controller/Entities/Photo.cs b/MediaBrowser.Controller/Entities/Photo.cs deleted file mode 100644 index 11db633bad..0000000000 --- a/MediaBrowser.Controller/Entities/Photo.cs +++ /dev/null @@ -1,110 +0,0 @@ -using MediaBrowser.Model.Drawing; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Controller.Entities -{ - public class Photo : BaseItem - { - [IgnoreDataMember] - public override bool SupportsLocalMetadata - { - get - { - return false; - } - } - - [IgnoreDataMember] - public override string MediaType - { - get - { - return Model.Entities.MediaType.Photo; - } - } - - [IgnoreDataMember] - public override Folder LatestItemsIndexContainer - { - get - { - return AlbumEntity; - } - } - - - [IgnoreDataMember] - public PhotoAlbum AlbumEntity - { - get - { - var parents = GetParents(); - foreach (var parent in parents) - { - var photoAlbum = parent as PhotoAlbum; - if (photoAlbum != null) - { - return photoAlbum; - } - } - return null; - } - } - - [IgnoreDataMember] - public override bool EnableRefreshOnDateModifiedChange - { - get { return true; } - } - - public override bool CanDownload() - { - return true; - } - - public override double? GetDefaultPrimaryImageAspectRatio() - { - if (Width.HasValue && Height.HasValue) - { - double width = Width.Value; - double height = Height.Value; - - if (Orientation.HasValue) - { - switch (Orientation.Value) - { - case ImageOrientation.LeftBottom: - case ImageOrientation.LeftTop: - case ImageOrientation.RightBottom: - case ImageOrientation.RightTop: - var temp = height; - height = width; - width = temp; - break; - } - } - - width /= Height.Value; - return width; - } - - return base.GetDefaultPrimaryImageAspectRatio(); - } - - public int? Width { get; set; } - public int? Height { get; set; } - public string CameraMake { get; set; } - public string CameraModel { get; set; } - public string Software { get; set; } - public double? ExposureTime { get; set; } - public double? FocalLength { get; set; } - public ImageOrientation? Orientation { get; set; } - public double? Aperture { get; set; } - public double? ShutterSpeed { get; set; } - - public double? Latitude { get; set; } - public double? Longitude { get; set; } - public double? Altitude { get; set; } - public int? IsoSpeedRating { get; set; } - } -} diff --git a/MediaBrowser.Controller/Entities/PhotoAlbum.cs b/MediaBrowser.Controller/Entities/PhotoAlbum.cs deleted file mode 100644 index af9d8c801d..0000000000 --- a/MediaBrowser.Controller/Entities/PhotoAlbum.cs +++ /dev/null @@ -1,34 +0,0 @@ -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Controller.Entities -{ - public class PhotoAlbum : Folder - { - [IgnoreDataMember] - public override bool AlwaysScanInternalMetadataPath - { - get - { - return true; - } - } - - [IgnoreDataMember] - public override bool SupportsPlayedStatus - { - get - { - return false; - } - } - - [IgnoreDataMember] - public override bool SupportsInheritedParentImages - { - get - { - return false; - } - } - } -} diff --git a/MediaBrowser.Controller/Entities/Share.cs b/MediaBrowser.Controller/Entities/Share.cs deleted file mode 100644 index e194f62388..0000000000 --- a/MediaBrowser.Controller/Entities/Share.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; - -namespace MediaBrowser.Controller.Entities -{ - public interface IHasShares - { - List<Share> Shares { get; set; } - } - - public class Share - { - public string UserId { get; set; } - public bool CanEdit { get; set; } - } -} diff --git a/MediaBrowser.Controller/Entities/SourceType.cs b/MediaBrowser.Controller/Entities/SourceType.cs deleted file mode 100644 index 9c307b4e6e..0000000000 --- a/MediaBrowser.Controller/Entities/SourceType.cs +++ /dev/null @@ -1,10 +0,0 @@ - -namespace MediaBrowser.Controller.Entities -{ - public enum SourceType - { - Library = 0, - Channel = 1, - LiveTV = 2 - } -} diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs deleted file mode 100644 index a6a72d9940..0000000000 --- a/MediaBrowser.Controller/Entities/Studio.cs +++ /dev/null @@ -1,154 +0,0 @@ -using System; -using System.Collections.Generic; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Common.Extensions; -using MediaBrowser.Controller.Extensions; -using MediaBrowser.Model.Extensions; - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Class Studio - /// </summary> - public class Studio : BaseItem, IItemByName - { - public override List<string> GetUserDataKeys() - { - var list = base.GetUserDataKeys(); - - list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics()); - return list; - } - public override string CreatePresentationUniqueKey() - { - return GetUserDataKeys()[0]; - } - - /// <summary> - /// Returns the folder containing the item. - /// If the item is a folder, it returns the folder itself - /// </summary> - /// <value>The containing folder path.</value> - [IgnoreDataMember] - public override string ContainingFolderPath - { - get - { - return Path; - } - } - - [IgnoreDataMember] - public override bool IsDisplayedAsFolder - { - get - { - return true; - } - } - - [IgnoreDataMember] - public override bool SupportsAncestors - { - get - { - return false; - } - } - - public override double? GetDefaultPrimaryImageAspectRatio() - { - double value = 16; - value /= 9; - - return value; - } - - public override bool CanDelete() - { - return false; - } - - public override bool IsSaveLocalMetadataEnabled() - { - return true; - } - - /// <summary> - /// Gets a value indicating whether this instance is owned item. - /// </summary> - /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public override bool IsOwnedItem - { - get - { - return false; - } - } - - public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query) - { - query.StudioIds = new[] { Id.ToString("N") }; - - return LibraryManager.GetItemList(query); - } - - [IgnoreDataMember] - public override bool SupportsPeople - { - get - { - return false; - } - } - - public static string GetPath(string name) - { - return GetPath(name, true); - } - - public static string GetPath(string name, bool normalizeName) - { - // Trim the period at the end because windows will have a hard time with that - var validName = normalizeName ? - FileSystem.GetValidFilename(name).Trim().TrimEnd('.') : - name; - - return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.StudioPath, validName); - } - - private string GetRebasedPath() - { - return GetPath(System.IO.Path.GetFileName(Path), false); - } - - public override bool RequiresRefresh() - { - var newPath = GetRebasedPath(); - if (!string.Equals(Path, newPath, StringComparison.Ordinal)) - { - Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath); - return true; - } - return base.RequiresRefresh(); - } - - /// <summary> - /// This is called before any metadata refresh and returns true or false indicating if changes were made - /// </summary> - public override bool BeforeMetadataRefresh() - { - var hasChanges = base.BeforeMetadataRefresh(); - - var newPath = GetRebasedPath(); - if (!string.Equals(Path, newPath, StringComparison.Ordinal)) - { - Path = newPath; - hasChanges = true; - } - - return hasChanges; - } - } -} diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs deleted file mode 100644 index 3f52dfc934..0000000000 --- a/MediaBrowser.Controller/Entities/TV/Episode.cs +++ /dev/null @@ -1,385 +0,0 @@ -using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Configuration;
-using MediaBrowser.Model.Entities;
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Serialization;
-
-namespace MediaBrowser.Controller.Entities.TV
-{
- /// <summary>
- /// Class Episode
- /// </summary>
- public class Episode : Video, IHasTrailers, IHasLookupInfo<EpisodeInfo>, IHasSeries
- {
- public Episode()
- {
- RemoteTrailers = EmptyMediaUrlArray;
- LocalTrailerIds = EmptyGuidArray;
- RemoteTrailerIds = EmptyGuidArray;
- }
-
- public Guid[] LocalTrailerIds { get; set; }
- public Guid[] RemoteTrailerIds { get; set; }
- public MediaUrl[] RemoteTrailers { get; set; }
-
- /// <summary>
- /// Gets the season in which it aired.
- /// </summary>
- /// <value>The aired season.</value>
- public int? AirsBeforeSeasonNumber { get; set; }
- public int? AirsAfterSeasonNumber { get; set; }
- public int? AirsBeforeEpisodeNumber { get; set; }
-
- /// <summary>
- /// Gets or sets the DVD season number.
- /// </summary>
- /// <value>The DVD season number.</value>
- public int? DvdSeasonNumber { get; set; }
- /// <summary>
- /// Gets or sets the DVD episode number.
- /// </summary>
- /// <value>The DVD episode number.</value>
- public float? DvdEpisodeNumber { get; set; }
-
- /// <summary>
- /// Gets or sets the absolute episode number.
- /// </summary>
- /// <value>The absolute episode number.</value>
- public int? AbsoluteEpisodeNumber { get; set; }
-
- /// <summary>
- /// This is the ending episode number for double episodes.
- /// </summary>
- /// <value>The index number.</value>
- public int? IndexNumberEnd { get; set; }
-
- public string FindSeriesSortName()
- {
- var series = Series;
- return series == null ? SeriesName : series.SortName;
- }
-
- [IgnoreDataMember]
- protected override bool SupportsOwnedItems
- {
- get
- {
- return IsStacked || MediaSourceCount > 1;
- }
- }
-
- [IgnoreDataMember]
- public override bool SupportsInheritedParentImages
- {
- get { return true; }
- }
-
- [IgnoreDataMember]
- public override bool SupportsPeople
- {
- get { return true; }
- }
-
- [IgnoreDataMember]
- public int? AiredSeasonNumber
- {
- get
- {
- return AirsAfterSeasonNumber ?? AirsBeforeSeasonNumber ?? ParentIndexNumber;
- }
- }
-
- [IgnoreDataMember]
- public override Folder LatestItemsIndexContainer
- {
- get
- {
- return Series;
- }
- }
-
- [IgnoreDataMember]
- public override Guid? DisplayParentId
- {
- get
- {
- return SeasonId;
- }
- }
-
- [IgnoreDataMember]
- protected override bool EnableDefaultVideoUserDataKeys
- {
- get
- {
- return false;
- }
- }
-
- public override double? GetDefaultPrimaryImageAspectRatio()
- {
- double value = 16;
- value /= 9;
-
- return value;
- }
-
- public override List<string> GetUserDataKeys()
- {
- var list = base.GetUserDataKeys();
-
- var series = Series;
- if (series != null && ParentIndexNumber.HasValue && IndexNumber.HasValue)
- {
- var seriesUserDataKeys = series.GetUserDataKeys();
- var take = seriesUserDataKeys.Count;
- if (seriesUserDataKeys.Count > 1)
- {
- take--;
- }
- list.InsertRange(0, seriesUserDataKeys.Take(take).Select(i => i + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000")));
- }
-
- return list;
- }
-
- /// <summary>
- /// This Episode's Series Instance
- /// </summary>
- /// <value>The series.</value>
- [IgnoreDataMember]
- public Series Series
- {
- get
- {
- var seriesId = SeriesId ?? FindSeriesId();
- return seriesId.HasValue ? (LibraryManager.GetItemById(seriesId.Value) as Series) : null;
- }
- }
-
- [IgnoreDataMember]
- public Season Season
- {
- get
- {
- var seasonId = SeasonId ?? FindSeasonId();
- return seasonId.HasValue ? (LibraryManager.GetItemById(seasonId.Value) as Season) : null;
- }
- }
-
- [IgnoreDataMember]
- public bool IsInSeasonFolder
- {
- get
- {
- return FindParent<Season>() != null;
- }
- }
-
- [IgnoreDataMember]
- public string SeriesPresentationUniqueKey { get; set; }
-
- [IgnoreDataMember]
- public string SeriesName { get; set; }
-
- [IgnoreDataMember]
- public string SeasonName { get; set; }
-
- public string FindSeriesPresentationUniqueKey()
- {
- var series = Series;
- return series == null ? null : series.PresentationUniqueKey;
- }
-
- public string FindSeasonName()
- {
- var season = Season;
-
- if (season == null)
- {
- if (ParentIndexNumber.HasValue)
- {
- return "Season " + ParentIndexNumber.Value.ToString(CultureInfo.InvariantCulture);
- }
- return "Season Unknown";
- }
-
- return season.Name;
- }
-
- public string FindSeriesName()
- {
- var series = Series;
- return series == null ? SeriesName : series.Name;
- }
-
- public Guid? FindSeasonId()
- {
- var season = FindParent<Season>();
-
- // Episodes directly in series folder
- if (season == null)
- {
- var series = Series;
-
- if (series != null && ParentIndexNumber.HasValue)
- {
- var findNumber = ParentIndexNumber.Value;
-
- season = series.Children
- .OfType<Season>()
- .FirstOrDefault(i => i.IndexNumber.HasValue && i.IndexNumber.Value == findNumber);
- }
- }
-
- return season == null ? (Guid?)null : season.Id;
- }
-
- /// <summary>
- /// Creates the name of the sort.
- /// </summary>
- /// <returns>System.String.</returns>
- protected override string CreateSortName()
- {
- return (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("000 - ") : "")
- + (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name;
- }
-
- /// <summary>
- /// Determines whether [contains episode number] [the specified number].
- /// </summary>
- /// <param name="number">The number.</param>
- /// <returns><c>true</c> if [contains episode number] [the specified number]; otherwise, <c>false</c>.</returns>
- public bool ContainsEpisodeNumber(int number)
- {
- if (IndexNumber.HasValue)
- {
- if (IndexNumberEnd.HasValue)
- {
- return number >= IndexNumber.Value && number <= IndexNumberEnd.Value;
- }
-
- return IndexNumber.Value == number;
- }
-
- return false;
- }
-
- [IgnoreDataMember]
- public override bool SupportsRemoteImageDownloading
- {
- get
- {
- if (IsMissingEpisode)
- {
- return false;
- }
-
- return true;
- }
- }
-
- [IgnoreDataMember]
- public bool IsMissingEpisode
- {
- get
- {
- return LocationType == LocationType.Virtual;
- }
- }
-
- [IgnoreDataMember]
- public Guid? SeasonId { get; set; }
- [IgnoreDataMember]
- public Guid? SeriesId { get; set; }
-
- public Guid? FindSeriesId()
- {
- var series = FindParent<Series>();
- return series == null ? (Guid?)null : series.Id;
- }
-
- public override IEnumerable<Guid> GetAncestorIds()
- {
- var list = base.GetAncestorIds().ToList();
-
- var seasonId = SeasonId;
-
- if (seasonId.HasValue && !list.Contains(seasonId.Value))
- {
- list.Add(seasonId.Value);
- }
-
- return list;
- }
-
- public override IEnumerable<FileSystemMetadata> GetDeletePaths()
- {
- return new[] {
- new FileSystemMetadata
- {
- FullName = Path,
- IsDirectory = IsFolder
- }
- }.Concat(GetLocalMetadataFilesToDelete());
- }
-
- public override UnratedItem GetBlockUnratedType()
- {
- return UnratedItem.Series;
- }
-
- public EpisodeInfo GetLookupInfo()
- {
- var id = GetItemLookupInfo<EpisodeInfo>();
-
- var series = Series;
-
- if (series != null)
- {
- id.SeriesProviderIds = series.ProviderIds;
- }
-
- id.IsMissingEpisode = IsMissingEpisode;
- id.IndexNumberEnd = IndexNumberEnd;
-
- return id;
- }
-
- public override bool BeforeMetadataRefresh()
- {
- var hasChanges = base.BeforeMetadataRefresh();
-
- try
- {
- if (LibraryManager.FillMissingEpisodeNumbersFromPath(this))
- {
- hasChanges = true;
- }
- }
- catch (Exception ex)
- {
- Logger.ErrorException("Error in FillMissingEpisodeNumbersFromPath. Episode: {0}", ex, Path ?? Name ?? Id.ToString());
- }
-
- if (!ParentIndexNumber.HasValue)
- {
- var season = Season;
- if (season != null)
- {
- if (season.ParentIndexNumber.HasValue)
- {
- ParentIndexNumber = season.ParentIndexNumber;
- hasChanges = true;
- }
- }
- }
-
- return hasChanges;
- }
- }
-}
diff --git a/MediaBrowser.Controller/Entities/TV/Season.cs b/MediaBrowser.Controller/Entities/TV/Season.cs deleted file mode 100644 index 00bb75fa78..0000000000 --- a/MediaBrowser.Controller/Entities/TV/Season.cs +++ /dev/null @@ -1,272 +0,0 @@ -using System; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Querying; -using MediaBrowser.Model.Users; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using MediaBrowser.Controller.Dto; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Controller.Entities.TV -{ - /// <summary> - /// Class Season - /// </summary> - public class Season : Folder, IHasSeries, IHasLookupInfo<SeasonInfo> - { - [IgnoreDataMember] - public override bool SupportsAddingToPlaylist - { - get { return true; } - } - - [IgnoreDataMember] - public override bool IsPreSorted - { - get - { - return true; - } - } - - [IgnoreDataMember] - public override bool SupportsDateLastMediaAdded - { - get - { - return false; - } - } - - [IgnoreDataMember] - public override bool SupportsPeople - { - get { return true; } - } - - [IgnoreDataMember] - public override bool SupportsInheritedParentImages - { - get { return true; } - } - - [IgnoreDataMember] - public override Guid? DisplayParentId - { - get { return SeriesId; } - } - - public override double? GetDefaultPrimaryImageAspectRatio() - { - double value = 2; - value /= 3; - - return value; - } - - public string FindSeriesSortName() - { - var series = Series; - return series == null ? SeriesName : series.SortName; - } - - public override List<string> GetUserDataKeys() - { - var list = base.GetUserDataKeys(); - - var series = Series; - if (series != null) - { - list.InsertRange(0, series.GetUserDataKeys().Select(i => i + (IndexNumber ?? 0).ToString("000"))); - } - - return list; - } - - public override int GetChildCount(User user) - { - var result = GetChildren(user, true).Count; - - return result; - } - - /// <summary> - /// This Episode's Series Instance - /// </summary> - /// <value>The series.</value> - [IgnoreDataMember] - public Series Series - { - get - { - var seriesId = SeriesId ?? FindSeriesId(); - return seriesId.HasValue ? (LibraryManager.GetItemById(seriesId.Value) as Series) : null; - } - } - - [IgnoreDataMember] - public string SeriesPath - { - get - { - var series = Series; - - if (series != null) - { - return series.Path; - } - - return FileSystem.GetDirectoryName(Path); - } - } - - public override string CreatePresentationUniqueKey() - { - if (IndexNumber.HasValue) - { - var series = Series; - if (series != null) - { - return series.PresentationUniqueKey + "-" + (IndexNumber ?? 0).ToString("000"); - } - } - - return base.CreatePresentationUniqueKey(); - } - - /// <summary> - /// Creates the name of the sort. - /// </summary> - /// <returns>System.String.</returns> - protected override string CreateSortName() - { - return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name; - } - - protected override QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query) - { - if (query.User == null) - { - return base.GetItemsInternal(query); - } - - var user = query.User; - - Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager); - - var items = GetEpisodes(user, query.DtoOptions).Where(filter); - - var result = PostFilterAndSort(items, query, false, false); - - return result; - } - - /// <summary> - /// Gets the episodes. - /// </summary> - public List<BaseItem> GetEpisodes(User user, DtoOptions options) - { - return GetEpisodes(Series, user, options); - } - - public List<BaseItem> GetEpisodes(Series series, User user, DtoOptions options) - { - return GetEpisodes(series, user, null, options); - } - - public List<BaseItem> GetEpisodes(Series series, User user, IEnumerable<Episode> allSeriesEpisodes, DtoOptions options) - { - return series.GetSeasonEpisodes(this, user, allSeriesEpisodes, options); - } - - public List<BaseItem> GetEpisodes() - { - return Series.GetSeasonEpisodes(this, null, null, new DtoOptions(true)); - } - - public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren) - { - return GetEpisodes(user, new DtoOptions(true)); - } - - protected override bool GetBlockUnratedValue(UserPolicy config) - { - // Don't block. Let either the entire series rating or episode rating determine it - return false; - } - - public override UnratedItem GetBlockUnratedType() - { - return UnratedItem.Series; - } - - [IgnoreDataMember] - public string SeriesPresentationUniqueKey { get; set; } - - [IgnoreDataMember] - public string SeriesName { get; set; } - - [IgnoreDataMember] - public Guid? SeriesId { get; set; } - - public string FindSeriesPresentationUniqueKey() - { - var series = Series; - return series == null ? null : series.PresentationUniqueKey; - } - - public string FindSeriesName() - { - var series = Series; - return series == null ? SeriesName : series.Name; - } - - public Guid? FindSeriesId() - { - var series = FindParent<Series>(); - return series == null ? (Guid?)null : series.Id; - } - - /// <summary> - /// Gets the lookup information. - /// </summary> - /// <returns>SeasonInfo.</returns> - public SeasonInfo GetLookupInfo() - { - var id = GetItemLookupInfo<SeasonInfo>(); - - var series = Series; - - if (series != null) - { - id.SeriesProviderIds = series.ProviderIds; - } - - return id; - } - - /// <summary> - /// This is called before any metadata refresh and returns true or false indicating if changes were made - /// </summary> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns> - public override bool BeforeMetadataRefresh() - { - var hasChanges = base.BeforeMetadataRefresh(); - - if (!IndexNumber.HasValue && !string.IsNullOrEmpty(Path)) - { - IndexNumber = IndexNumber ?? LibraryManager.GetSeasonNumberFromPath(Path); - - // If a change was made record it - if (IndexNumber.HasValue) - { - hasChanges = true; - } - } - - return hasChanges; - } - } -} diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs deleted file mode 100644 index ccd0a76369..0000000000 --- a/MediaBrowser.Controller/Entities/TV/Series.cs +++ /dev/null @@ -1,559 +0,0 @@ -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Querying; -using MediaBrowser.Model.Users; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Dto; -using MediaBrowser.Model.Extensions; -using MediaBrowser.Model.Providers; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Controller.Entities.TV -{ - /// <summary> - /// Class Series - /// </summary> - public class Series : Folder, IHasTrailers, IHasDisplayOrder, IHasLookupInfo<SeriesInfo>, IMetadataContainer - { - public Series() - { - RemoteTrailers = EmptyMediaUrlArray; - LocalTrailerIds = EmptyGuidArray; - RemoteTrailerIds = EmptyGuidArray; - AirDays = new DayOfWeek[] { }; - } - - public DayOfWeek[] AirDays { get; set; } - public string AirTime { get; set; } - - [IgnoreDataMember] - public override bool SupportsAddingToPlaylist - { - get { return true; } - } - - [IgnoreDataMember] - public override bool IsPreSorted - { - get - { - return true; - } - } - - [IgnoreDataMember] - public override bool SupportsDateLastMediaAdded - { - get - { - return true; - } - } - - [IgnoreDataMember] - public override bool SupportsInheritedParentImages - { - get - { - return false; - } - } - - [IgnoreDataMember] - public override bool SupportsPeople - { - get { return true; } - } - - public Guid[] LocalTrailerIds { get; set; } - public Guid[] RemoteTrailerIds { get; set; } - - public MediaUrl[] RemoteTrailers { get; set; } - - /// <summary> - /// airdate, dvd or absolute - /// </summary> - public string DisplayOrder { get; set; } - - /// <summary> - /// Gets or sets the status. - /// </summary> - /// <value>The status.</value> - public SeriesStatus? Status { get; set; } - - /// <summary> - /// Gets or sets the date last episode added. - /// </summary> - /// <value>The date last episode added.</value> - [IgnoreDataMember] - public DateTime DateLastEpisodeAdded - { - get - { - return DateLastMediaAdded ?? DateTime.MinValue; - } - } - - public override double? GetDefaultPrimaryImageAspectRatio() - { - double value = 2; - value /= 3; - - return value; - } - - public override string CreatePresentationUniqueKey() - { - if (LibraryManager.GetLibraryOptions(this).EnableAutomaticSeriesGrouping) - { - var userdatakeys = GetUserDataKeys(); - - if (userdatakeys.Count > 1) - { - return AddLibrariesToPresentationUniqueKey(userdatakeys[0]); - } - } - - return base.CreatePresentationUniqueKey(); - } - - private string AddLibrariesToPresentationUniqueKey(string key) - { - var lang = GetPreferredMetadataLanguage(); - if (!string.IsNullOrWhiteSpace(lang)) - { - key += "-" + lang; - } - - var folders = LibraryManager.GetCollectionFolders(this) - .Select(i => i.Id.ToString("N")) - .ToArray(); - - if (folders.Length == 0) - { - return key; - } - - return key + "-" + string.Join("-", folders); - } - - private static string GetUniqueSeriesKey(BaseItem series) - { - return series.GetPresentationUniqueKey(); - } - - public override int GetChildCount(User user) - { - var seriesKey = GetUniqueSeriesKey(this); - - var result = LibraryManager.GetCount(new InternalItemsQuery(user) - { - AncestorWithPresentationUniqueKey = null, - SeriesPresentationUniqueKey = seriesKey, - IncludeItemTypes = new[] { typeof(Season).Name }, - IsVirtualItem = false, - Limit = 0, - DtoOptions = new Dto.DtoOptions(false) - { - EnableImages = false - } - }); - - return result; - } - - public override int GetRecursiveChildCount(User user) - { - var seriesKey = GetUniqueSeriesKey(this); - - var query = new InternalItemsQuery(user) - { - AncestorWithPresentationUniqueKey = null, - SeriesPresentationUniqueKey = seriesKey, - DtoOptions = new Dto.DtoOptions(false) - { - EnableImages = false - } - }; - - if (query.IncludeItemTypes.Length == 0) - { - query.IncludeItemTypes = new[] { typeof(Episode).Name }; - } - query.IsVirtualItem = false; - query.Limit = 0; - var totalRecordCount = LibraryManager.GetCount(query); - - return totalRecordCount; - } - - /// <summary> - /// Gets the user data key. - /// </summary> - /// <returns>System.String.</returns> - public override List<string> GetUserDataKeys() - { - var list = base.GetUserDataKeys(); - - var key = this.GetProviderId(MetadataProviders.Imdb); - if (!string.IsNullOrWhiteSpace(key)) - { - list.Insert(0, key); - } - - key = this.GetProviderId(MetadataProviders.Tvdb); - if (!string.IsNullOrWhiteSpace(key)) - { - list.Insert(0, key); - } - - return list; - } - - public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren) - { - return GetSeasons(user, new DtoOptions(true)); - } - - public List<BaseItem> GetSeasons(User user, DtoOptions options) - { - var query = new InternalItemsQuery(user) - { - DtoOptions = options - }; - - SetSeasonQueryOptions(query, user); - - return LibraryManager.GetItemList(query); - } - - private void SetSeasonQueryOptions(InternalItemsQuery query, User user) - { - var config = user.Configuration; - - var seriesKey = GetUniqueSeriesKey(this); - - query.AncestorWithPresentationUniqueKey = null; - query.SeriesPresentationUniqueKey = seriesKey; - query.IncludeItemTypes = new[] { typeof(Season).Name }; - query.OrderBy = new[] { ItemSortBy.SortName }.Select(i => new Tuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(); - - if (!config.DisplayMissingEpisodes) - { - query.IsMissing = false; - } - } - - protected override QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query) - { - if (query.User == null) - { - return base.GetItemsInternal(query); - } - - var user = query.User; - - if (query.Recursive) - { - var seriesKey = GetUniqueSeriesKey(this); - - query.AncestorWithPresentationUniqueKey = null; - query.SeriesPresentationUniqueKey = seriesKey; - if (query.OrderBy.Length == 0) - { - query.OrderBy = new[] { ItemSortBy.SortName }.Select(i => new Tuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(); - } - if (query.IncludeItemTypes.Length == 0) - { - query.IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name }; - } - query.IsVirtualItem = false; - return LibraryManager.GetItemsResult(query); - } - - SetSeasonQueryOptions(query, user); - - return LibraryManager.GetItemsResult(query); - } - - public IEnumerable<BaseItem> GetEpisodes(User user, DtoOptions options) - { - var seriesKey = GetUniqueSeriesKey(this); - - var query = new InternalItemsQuery(user) - { - AncestorWithPresentationUniqueKey = null, - SeriesPresentationUniqueKey = seriesKey, - IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name }, - OrderBy = new[] { ItemSortBy.SortName }.Select(i => new Tuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(), - DtoOptions = options - }; - var config = user.Configuration; - if (!config.DisplayMissingEpisodes) - { - query.IsMissing = false; - } - - var allItems = LibraryManager.GetItemList(query); - - var allSeriesEpisodes = allItems.OfType<Episode>().ToList(); - - var allEpisodes = allItems.OfType<Season>() - .SelectMany(i => i.GetEpisodes(this, user, allSeriesEpisodes, options)) - .Reverse(); - - // Specials could appear twice based on above - once in season 0, once in the aired season - // This depends on settings for that series - // When this happens, remove the duplicate from season 0 - - return allEpisodes.DistinctBy(i => i.Id).Reverse(); - } - - public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken) - { - // Refresh bottom up, children first, then the boxset - // By then hopefully the movies within will have Tmdb collection values - var items = GetRecursiveChildren(); - - var totalItems = items.Count; - var numComplete = 0; - - // Refresh current item - await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); - - // Refresh seasons - foreach (var item in items) - { - if (!(item is Season)) - { - continue; - } - - cancellationToken.ThrowIfCancellationRequested(); - - if (refreshOptions.RefreshItem(item)) - { - await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); - } - - numComplete++; - double percent = numComplete; - percent /= totalItems; - progress.Report(percent * 100); - } - - // Refresh episodes and other children - foreach (var item in items) - { - if ((item is Season)) - { - continue; - } - - cancellationToken.ThrowIfCancellationRequested(); - - var skipItem = false; - - var episode = item as Episode; - - if (episode != null - && refreshOptions.MetadataRefreshMode != MetadataRefreshMode.FullRefresh - && !refreshOptions.ReplaceAllMetadata - && episode.IsMissingEpisode - && episode.LocationType == LocationType.Virtual - && episode.PremiereDate.HasValue - && (DateTime.UtcNow - episode.PremiereDate.Value).TotalDays > 30) - { - skipItem = true; - } - - if (!skipItem) - { - if (refreshOptions.RefreshItem(item)) - { - await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false); - } - } - - numComplete++; - double percent = numComplete; - percent /= totalItems; - progress.Report(percent * 100); - } - - refreshOptions = new MetadataRefreshOptions(refreshOptions); - refreshOptions.IsPostRecursiveRefresh = true; - await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false); - } - - public List<BaseItem> GetSeasonEpisodes(Season parentSeason, User user, DtoOptions options) - { - var queryFromSeries = ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons; - - // add optimization when this setting is not enabled - var seriesKey = queryFromSeries ? - GetUniqueSeriesKey(this) : - GetUniqueSeriesKey(parentSeason); - - var query = new InternalItemsQuery(user) - { - AncestorWithPresentationUniqueKey = queryFromSeries ? null : seriesKey, - SeriesPresentationUniqueKey = queryFromSeries ? seriesKey : null, - IncludeItemTypes = new[] { typeof(Episode).Name }, - OrderBy = new[] { ItemSortBy.SortName }.Select(i => new Tuple<string, SortOrder>(i, SortOrder.Ascending)).ToArray(), - DtoOptions = options - }; - if (user != null) - { - var config = user.Configuration; - if (!config.DisplayMissingEpisodes) - { - query.IsMissing = false; - } - } - - var allItems = LibraryManager.GetItemList(query); - - return GetSeasonEpisodes(parentSeason, user, allItems, options); - } - - public List<BaseItem> GetSeasonEpisodes(Season parentSeason, User user, IEnumerable<BaseItem> allSeriesEpisodes, DtoOptions options) - { - if (allSeriesEpisodes == null) - { - return GetSeasonEpisodes(parentSeason, user, options); - } - - var episodes = FilterEpisodesBySeason(allSeriesEpisodes, parentSeason, ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons); - - var sortBy = (parentSeason.IndexNumber ?? -1) == 0 ? ItemSortBy.SortName : ItemSortBy.AiredEpisodeOrder; - - return LibraryManager.Sort(episodes, user, new[] { sortBy }, SortOrder.Ascending).ToList(); - } - - /// <summary> - /// Filters the episodes by season. - /// </summary> - public static IEnumerable<BaseItem> FilterEpisodesBySeason(IEnumerable<BaseItem> episodes, Season parentSeason, bool includeSpecials) - { - var seasonNumber = parentSeason.IndexNumber; - var seasonPresentationKey = GetUniqueSeriesKey(parentSeason); - - var supportSpecialsInSeason = includeSpecials && seasonNumber.HasValue && seasonNumber.Value != 0; - - return episodes.Where(episode => - { - var episodeItem = (Episode)episode; - - var currentSeasonNumber = supportSpecialsInSeason ? episodeItem.AiredSeasonNumber : episode.ParentIndexNumber; - if (currentSeasonNumber.HasValue && seasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber.Value) - { - return true; - } - - if (!currentSeasonNumber.HasValue && !seasonNumber.HasValue && parentSeason.LocationType == LocationType.Virtual) - { - return true; - } - - var season = episodeItem.Season; - return season != null && string.Equals(GetUniqueSeriesKey(season), seasonPresentationKey, StringComparison.OrdinalIgnoreCase); - }); - } - - /// <summary> - /// Filters the episodes by season. - /// </summary> - public static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, int seasonNumber, bool includeSpecials) - { - if (!includeSpecials || seasonNumber < 1) - { - return episodes.Where(i => (i.ParentIndexNumber ?? -1) == seasonNumber); - } - - return episodes.Where(i => - { - var episode = i; - - if (episode != null) - { - var currentSeasonNumber = episode.AiredSeasonNumber; - - return currentSeasonNumber.HasValue && currentSeasonNumber.Value == seasonNumber; - } - - return false; - }); - } - - - protected override bool GetBlockUnratedValue(UserPolicy config) - { - return config.BlockUnratedItems.Contains(UnratedItem.Series); - } - - public override UnratedItem GetBlockUnratedType() - { - return UnratedItem.Series; - } - - public SeriesInfo GetLookupInfo() - { - var info = GetItemLookupInfo<SeriesInfo>(); - - return info; - } - - public override bool BeforeMetadataRefresh() - { - var hasChanges = base.BeforeMetadataRefresh(); - - if (!ProductionYear.HasValue) - { - var info = LibraryManager.ParseName(Name); - - var yearInName = info.Year; - - if (yearInName.HasValue) - { - ProductionYear = yearInName; - hasChanges = true; - } - } - - return hasChanges; - } - - public override List<ExternalUrl> GetRelatedUrls() - { - var list = base.GetRelatedUrls(); - - var imdbId = this.GetProviderId(MetadataProviders.Imdb); - if (!string.IsNullOrWhiteSpace(imdbId)) - { - list.Add(new ExternalUrl - { - Name = "Trakt", - Url = string.Format("https://trakt.tv/shows/{0}", imdbId) - }); - } - - return list; - } - - [IgnoreDataMember] - public override bool StopRefreshIfLocalMetadataFound - { - get - { - // Need people id's from internet metadata - return false; - } - } - } -} diff --git a/MediaBrowser.Controller/Entities/TagExtensions.cs b/MediaBrowser.Controller/Entities/TagExtensions.cs deleted file mode 100644 index e5d8f35d92..0000000000 --- a/MediaBrowser.Controller/Entities/TagExtensions.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using MediaBrowser.Model.Extensions; - -namespace MediaBrowser.Controller.Entities -{ - public static class TagExtensions - { - public static void AddTag(this BaseItem item, string name) - { - if (string.IsNullOrWhiteSpace(name)) - { - throw new ArgumentNullException("name"); - } - - var current = item.Tags; - - if (!current.Contains(name, StringComparer.OrdinalIgnoreCase)) - { - if (current.Length == 0) - { - item.Tags = new[] { name }; - } - else - { - var list = current.ToArray(current.Length + 1); - list[list.Length - 1] = name; - - item.Tags = list; - } - } - } - } -} diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs deleted file mode 100644 index c5144aadf4..0000000000 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ /dev/null @@ -1,121 +0,0 @@ -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Entities; -using System.Collections.Generic; -using MediaBrowser.Model.Providers; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Class Trailer - /// </summary> - public class Trailer : Video, IHasLookupInfo<TrailerInfo> - { - public Trailer() - { - RemoteTrailers = new List<MediaUrl>(); - TrailerTypes = new List<TrailerType> { TrailerType.LocalTrailer }; - } - - public List<TrailerType> TrailerTypes { get; set; } - - public List<MediaUrl> RemoteTrailers { get; set; } - - [IgnoreDataMember] - public bool IsLocalTrailer - { - get { return TrailerTypes.Contains(TrailerType.LocalTrailer); } - } - - public override double? GetDefaultPrimaryImageAspectRatio() - { - double value = 2; - value /= 3; - - return value; - } - - public override UnratedItem GetBlockUnratedType() - { - return UnratedItem.Trailer; - } - - public TrailerInfo GetLookupInfo() - { - var info = GetItemLookupInfo<TrailerInfo>(); - - info.IsLocalTrailer = TrailerTypes.Contains(TrailerType.LocalTrailer); - - if (!IsInMixedFolder && LocationType == LocationType.FileSystem) - { - info.Name = System.IO.Path.GetFileName(ContainingFolderPath); - } - - return info; - } - - public override bool BeforeMetadataRefresh() - { - var hasChanges = base.BeforeMetadataRefresh(); - - if (!ProductionYear.HasValue) - { - var info = LibraryManager.ParseName(Name); - - var yearInName = info.Year; - - if (yearInName.HasValue) - { - ProductionYear = yearInName; - hasChanges = true; - } - else - { - // Try to get the year from the folder name - if (!IsInMixedFolder) - { - info = LibraryManager.ParseName(System.IO.Path.GetFileName(ContainingFolderPath)); - - yearInName = info.Year; - - if (yearInName.HasValue) - { - ProductionYear = yearInName; - hasChanges = true; - } - } - } - } - - return hasChanges; - } - - public override List<ExternalUrl> GetRelatedUrls() - { - var list = base.GetRelatedUrls(); - - var imdbId = this.GetProviderId(MetadataProviders.Imdb); - if (!string.IsNullOrWhiteSpace(imdbId)) - { - list.Add(new ExternalUrl - { - Name = "Trakt", - Url = string.Format("https://trakt.tv/movies/{0}", imdbId) - }); - } - - return list; - } - - [IgnoreDataMember] - public override bool StopRefreshIfLocalMetadataFound - { - get - { - // Need people id's from internet metadata - return false; - } - } - } -} diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs deleted file mode 100644 index 821327b7f3..0000000000 --- a/MediaBrowser.Controller/Entities/User.cs +++ /dev/null @@ -1,351 +0,0 @@ -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Connect; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.Users; -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Class User - /// </summary> - public class User : BaseItem - { - public static IUserManager UserManager { get; set; } - public static IXmlSerializer XmlSerializer { get; set; } - - /// <summary> - /// From now on all user paths will be Id-based. - /// This is for backwards compatibility. - /// </summary> - public bool UsesIdForConfigurationPath { get; set; } - - /// <summary> - /// Gets or sets the password. - /// </summary> - /// <value>The password.</value> - public string Password { get; set; } - public string EasyPassword { get; set; } - public string Salt { get; set; } - - public string ConnectUserName { get; set; } - public string ConnectUserId { get; set; } - public UserLinkType? ConnectLinkType { get; set; } - public string ConnectAccessKey { get; set; } - - // Strictly to remove IgnoreDataMember - public override ItemImageInfo[] ImageInfos - { - get - { - return base.ImageInfos; - } - set - { - base.ImageInfos = value; - } - } - - /// <summary> - /// Gets or sets the path. - /// </summary> - /// <value>The path.</value> - [IgnoreDataMember] - public override string Path - { - get - { - // Return this so that metadata providers will look in here - return ConfigurationDirectoryPath; - } - set - { - base.Path = value; - } - } - - private string _name; - /// <summary> - /// Gets or sets the name. - /// </summary> - /// <value>The name.</value> - public override string Name - { - get - { - return _name; - } - set - { - _name = value; - - // lazy load this again - SortName = null; - } - } - - /// <summary> - /// Returns the folder containing the item. - /// If the item is a folder, it returns the folder itself - /// </summary> - /// <value>The containing folder path.</value> - [IgnoreDataMember] - public override string ContainingFolderPath - { - get - { - return Path; - } - } - - /// <summary> - /// Gets a value indicating whether this instance is owned item. - /// </summary> - /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public override bool IsOwnedItem - { - get - { - return false; - } - } - - /// <summary> - /// Gets the root folder. - /// </summary> - /// <value>The root folder.</value> - [IgnoreDataMember] - public Folder RootFolder - { - get - { - return LibraryManager.GetUserRootFolder(); - } - } - - /// <summary> - /// Gets or sets the last login date. - /// </summary> - /// <value>The last login date.</value> - public DateTime? LastLoginDate { get; set; } - /// <summary> - /// Gets or sets the last activity date. - /// </summary> - /// <value>The last activity date.</value> - public DateTime? LastActivityDate { get; set; } - - private volatile UserConfiguration _config; - private readonly object _configSyncLock = new object(); - [IgnoreDataMember] - public UserConfiguration Configuration - { - get - { - if (_config == null) - { - lock (_configSyncLock) - { - if (_config == null) - { - _config = UserManager.GetUserConfiguration(this); - } - } - } - - return _config; - } - set { _config = value; } - } - - private volatile UserPolicy _policy; - private readonly object _policySyncLock = new object(); - [IgnoreDataMember] - public UserPolicy Policy - { - get - { - if (_policy == null) - { - lock (_policySyncLock) - { - if (_policy == null) - { - _policy = UserManager.GetUserPolicy(this); - } - } - } - - return _policy; - } - set { _policy = value; } - } - - /// <summary> - /// Renames the user. - /// </summary> - /// <param name="newName">The new name.</param> - /// <returns>Task.</returns> - /// <exception cref="System.ArgumentNullException"></exception> - public Task Rename(string newName) - { - if (string.IsNullOrEmpty(newName)) - { - throw new ArgumentNullException("newName"); - } - - // If only the casing is changing, leave the file system alone - if (!UsesIdForConfigurationPath && !string.Equals(newName, Name, StringComparison.OrdinalIgnoreCase)) - { - UsesIdForConfigurationPath = true; - - // Move configuration - var newConfigDirectory = GetConfigurationDirectoryPath(newName); - var oldConfigurationDirectory = ConfigurationDirectoryPath; - - // Exceptions will be thrown if these paths already exist - if (FileSystem.DirectoryExists(newConfigDirectory)) - { - FileSystem.DeleteDirectory(newConfigDirectory, true); - } - - if (FileSystem.DirectoryExists(oldConfigurationDirectory)) - { - FileSystem.MoveDirectory(oldConfigurationDirectory, newConfigDirectory); - } - else - { - FileSystem.CreateDirectory(newConfigDirectory); - } - } - - Name = newName; - - return RefreshMetadata(new MetadataRefreshOptions(new DirectoryService(Logger, FileSystem)) - { - ReplaceAllMetadata = true, - ImageRefreshMode = ImageRefreshMode.FullRefresh, - MetadataRefreshMode = MetadataRefreshMode.FullRefresh, - ForceSave = true - - }, CancellationToken.None); - } - - public override void UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken) - { - UserManager.UpdateUser(this); - } - - /// <summary> - /// Gets the path to the user's configuration directory - /// </summary> - /// <value>The configuration directory path.</value> - [IgnoreDataMember] - public string ConfigurationDirectoryPath - { - get - { - return GetConfigurationDirectoryPath(Name); - } - } - - public override double? GetDefaultPrimaryImageAspectRatio() - { - return 1; - } - - /// <summary> - /// Gets the configuration directory path. - /// </summary> - /// <param name="username">The username.</param> - /// <returns>System.String.</returns> - private string GetConfigurationDirectoryPath(string username) - { - var parentPath = ConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath; - - // Legacy - if (!UsesIdForConfigurationPath) - { - if (string.IsNullOrEmpty(username)) - { - throw new ArgumentNullException("username"); - } - - var safeFolderName = FileSystem.GetValidFilename(username); - - return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.UserConfigurationDirectoryPath, safeFolderName); - } - - return System.IO.Path.Combine(parentPath, Id.ToString("N")); - } - - public bool IsParentalScheduleAllowed() - { - return IsParentalScheduleAllowed(DateTime.UtcNow); - } - - public bool IsParentalScheduleAllowed(DateTime date) - { - var schedules = Policy.AccessSchedules; - - if (schedules.Length == 0) - { - return true; - } - - foreach (var i in schedules) - { - if (IsParentalScheduleAllowed(i, date)) - { - return true; - } - } - return false; - } - - private bool IsParentalScheduleAllowed(AccessSchedule schedule, DateTime date) - { - if (date.Kind != DateTimeKind.Utc) - { - throw new ArgumentException("Utc date expected"); - } - - var localTime = date.ToLocalTime(); - - return DayOfWeekHelper.GetDaysOfWeek(schedule.DayOfWeek).Contains(localTime.DayOfWeek) && - IsWithinTime(schedule, localTime); - } - - private bool IsWithinTime(AccessSchedule schedule, DateTime localTime) - { - var hour = localTime.TimeOfDay.TotalHours; - - return hour >= schedule.StartHour && hour <= schedule.EndHour; - } - - public bool IsFolderGrouped(Guid id) - { - foreach (var i in Configuration.GroupedFolders) - { - if (new Guid(i) == id) - { - return true; - } - } - return false; - } - - [IgnoreDataMember] - public override bool SupportsPeople - { - get - { - return false; - } - } - } -} diff --git a/MediaBrowser.Controller/Entities/UserItemData.cs b/MediaBrowser.Controller/Entities/UserItemData.cs deleted file mode 100644 index 0e13269499..0000000000 --- a/MediaBrowser.Controller/Entities/UserItemData.cs +++ /dev/null @@ -1,124 +0,0 @@ -using System; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Class UserItemData - /// </summary> - public class UserItemData - { - /// <summary> - /// Gets or sets the user id. - /// </summary> - /// <value>The user id.</value> - public Guid UserId { get; set; } - - /// <summary> - /// Gets or sets the key. - /// </summary> - /// <value>The key.</value> - public string Key { get; set; } - - /// <summary> - /// The _rating - /// </summary> - private double? _rating; - /// <summary> - /// Gets or sets the users 0-10 rating - /// </summary> - /// <value>The rating.</value> - /// <exception cref="System.ArgumentOutOfRangeException">Rating;A 0 to 10 rating is required for UserItemData.</exception> - public double? Rating - { - get - { - return _rating; - } - set - { - if (value.HasValue) - { - if (value.Value < 0 || value.Value > 10) - { - throw new ArgumentOutOfRangeException("value", "A 0 to 10 rating is required for UserItemData."); - } - } - - _rating = value; - } - } - - /// <summary> - /// Gets or sets the playback position ticks. - /// </summary> - /// <value>The playback position ticks.</value> - public long PlaybackPositionTicks { get; set; } - - /// <summary> - /// Gets or sets the play count. - /// </summary> - /// <value>The play count.</value> - public int PlayCount { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether this instance is favorite. - /// </summary> - /// <value><c>true</c> if this instance is favorite; otherwise, <c>false</c>.</value> - public bool IsFavorite { get; set; } - - /// <summary> - /// Gets or sets the last played date. - /// </summary> - /// <value>The last played date.</value> - public DateTime? LastPlayedDate { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether this <see cref="UserItemData" /> is played. - /// </summary> - /// <value><c>true</c> if played; otherwise, <c>false</c>.</value> - public bool Played { get; set; } - /// <summary> - /// Gets or sets the index of the audio stream. - /// </summary> - /// <value>The index of the audio stream.</value> - public int? AudioStreamIndex { get; set; } - /// <summary> - /// Gets or sets the index of the subtitle stream. - /// </summary> - /// <value>The index of the subtitle stream.</value> - public int? SubtitleStreamIndex { get; set; } - - public const double MinLikeValue = 6.5; - - /// <summary> - /// This is an interpreted property to indicate likes or dislikes - /// This should never be serialized. - /// </summary> - /// <value><c>null</c> if [likes] contains no value, <c>true</c> if [likes]; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public bool? Likes - { - get - { - if (Rating != null) - { - return Rating >= MinLikeValue; - } - - return null; - } - set - { - if (value.HasValue) - { - Rating = value.Value ? 10 : 1; - } - else - { - Rating = null; - } - } - } - } -} diff --git a/MediaBrowser.Controller/Entities/UserRootFolder.cs b/MediaBrowser.Controller/Entities/UserRootFolder.cs deleted file mode 100644 index 2ed3bf20fa..0000000000 --- a/MediaBrowser.Controller/Entities/UserRootFolder.cs +++ /dev/null @@ -1,156 +0,0 @@ -using MediaBrowser.Model.Serialization; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Library; -using MediaBrowser.Model.Querying; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Special class used for User Roots. Children contain actual ones defined for this user - /// PLUS the virtual folders from the physical root (added by plug-ins). - /// </summary> - public class UserRootFolder : Folder - { - private List<Guid> _childrenIds = null; - private readonly object _childIdsLock = new object(); - protected override List<BaseItem> LoadChildren() - { - lock (_childIdsLock) - { - if (_childrenIds == null) - { - var list = base.LoadChildren(); - _childrenIds = list.Select(i => i.Id).ToList(); - return list; - } - - return _childrenIds.Select(LibraryManager.GetItemById).Where(i => i != null).ToList(); - } - } - - [IgnoreDataMember] - public override bool SupportsInheritedParentImages - { - get - { - return false; - } - } - - [IgnoreDataMember] - public override bool SupportsPlayedStatus - { - get - { - return false; - } - } - - private void ClearCache() - { - lock (_childIdsLock) - { - _childrenIds = null; - } - } - - protected override QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query) - { - if (query.Recursive) - { - return QueryRecursive(query); - } - - var result = UserViewManager.GetUserViews(new UserViewQuery - { - UserId = query.User.Id.ToString("N"), - PresetViews = query.PresetViews - - }, CancellationToken.None).Result; - - var user = query.User; - Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager); - - return PostFilterAndSort(result.Where(filter), query, true, true); - } - - public override int GetChildCount(User user) - { - return GetChildren(user, true).Count; - } - - [IgnoreDataMember] - protected override bool SupportsShortcutChildren - { - get - { - return true; - } - } - - [IgnoreDataMember] - public override bool IsPreSorted - { - get - { - return true; - } - } - - protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user) - { - var list = base.GetEligibleChildrenForRecursiveChildren(user).ToList(); - list.AddRange(LibraryManager.RootFolder.VirtualChildren); - - return list; - } - - public override bool BeforeMetadataRefresh() - { - ClearCache(); - - var hasChanges = base.BeforeMetadataRefresh(); - - if (string.Equals("default", Name, StringComparison.OrdinalIgnoreCase)) - { - Name = "Media Folders"; - hasChanges = true; - } - - return hasChanges; - } - - protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService) - { - ClearCache(); - - return base.GetNonCachedChildren(directoryService); - } - - protected override async Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService) - { - ClearCache(); - - await base.ValidateChildrenInternal(progress, cancellationToken, recursive, refreshChildMetadata, refreshOptions, directoryService) - .ConfigureAwait(false); - - ClearCache(); - - // Not the best way to handle this, but it solves an issue - // CollectionFolders aren't always getting saved after changes - // This means that grabbing the item by Id may end up returning the old one - // Fix is in two places - make sure the folder gets saved - // And here to remedy it for affected users. - // In theory this can be removed eventually. - foreach (var item in Children) - { - LibraryManager.RegisterItem(item); - } - } - } -} diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs deleted file mode 100644 index 2152e65cfb..0000000000 --- a/MediaBrowser.Controller/Entities/UserView.cs +++ /dev/null @@ -1,207 +0,0 @@ -using MediaBrowser.Controller.Playlists; -using MediaBrowser.Controller.TV; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Querying; -using System; -using System.Collections.Generic; -using System.Linq; -using MediaBrowser.Model.Serialization; -using System.Threading.Tasks; -using MediaBrowser.Controller.Dto; - -namespace MediaBrowser.Controller.Entities -{ - public class UserView : Folder - { - public string ViewType { get; set; } - public Guid DisplayParentId { get; set; } - - public Guid? UserId { get; set; } - - public static ITVSeriesManager TVSeriesManager; - public static IPlaylistManager PlaylistManager; - - public override IEnumerable<Guid> GetIdsForAncestorQuery() - { - var list = new List<Guid>(); - - if (DisplayParentId != Guid.Empty) - { - list.Add(DisplayParentId); - } - else if (ParentId != Guid.Empty) - { - list.Add(ParentId); - } - else - { - list.Add(Id); - } - return list; - } - - [IgnoreDataMember] - public override bool SupportsInheritedParentImages - { - get - { - return false; - } - } - - [IgnoreDataMember] - public override bool SupportsPlayedStatus - { - get - { - return false; - } - } - - //public override double? GetDefaultPrimaryImageAspectRatio() - //{ - // double value = 16; - // value /= 9; - - // return value; - //} - - public override int GetChildCount(User user) - { - return GetChildren(user, true).Count; - } - - protected override QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query) - { - var parent = this as Folder; - - if (DisplayParentId != Guid.Empty) - { - parent = LibraryManager.GetItemById(DisplayParentId) as Folder ?? parent; - } - else if (ParentId != Guid.Empty) - { - parent = LibraryManager.GetItemById(ParentId) as Folder ?? parent; - } - - return new UserViewBuilder(UserViewManager, LiveTvManager, ChannelManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, ConfigurationManager, PlaylistManager) - .GetUserItems(parent, this, ViewType, query).Result; - } - - public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren) - { - var result = GetItemList(new InternalItemsQuery - { - User = user, - EnableTotalRecordCount = false, - DtoOptions = new DtoOptions(true) - - }); - - return result.ToList(); - } - - public override bool CanDelete() - { - return false; - } - - public override bool IsSaveLocalMetadataEnabled() - { - return true; - } - - public override IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query) - { - var result = GetItemList(new InternalItemsQuery - { - User = user, - Recursive = true, - EnableTotalRecordCount = false, - - ForceDirect = true, - - DtoOptions = query.DtoOptions - - }); - - return result.Where(i => UserViewBuilder.FilterItem(i, query)); - } - - protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user) - { - return GetChildren(user, false); - } - - public static bool IsUserSpecific(Folder folder) - { - var standaloneTypes = new List<string> - { - CollectionType.Playlists - }; - - var collectionFolder = folder as ICollectionFolder; - - if (collectionFolder == null) - { - return false; - } - - var supportsUserSpecific = folder as ISupportsUserSpecificView; - if (supportsUserSpecific != null && supportsUserSpecific.EnableUserSpecificView) - { - return true; - } - - return standaloneTypes.Contains(collectionFolder.CollectionType ?? string.Empty); - } - - public static bool IsEligibleForGrouping(Folder folder) - { - var collectionFolder = folder as ICollectionFolder; - return collectionFolder != null && IsEligibleForGrouping(collectionFolder.CollectionType); - } - - public static bool IsEligibleForGrouping(string viewType) - { - var types = new[] - { - CollectionType.Movies, - CollectionType.TvShows, - string.Empty - }; - - return types.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase); - } - - public static bool EnableOriginalFolder(string viewType) - { - var types = new[] - { - CollectionType.Games, - CollectionType.Books, - CollectionType.MusicVideos, - CollectionType.HomeVideos, - CollectionType.Photos, - CollectionType.Music, - CollectionType.BoxSets - }; - - return types.Contains(viewType ?? string.Empty, StringComparer.OrdinalIgnoreCase); - } - - protected override Task ValidateChildrenInternal(IProgress<double> progress, System.Threading.CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, Providers.MetadataRefreshOptions refreshOptions, Providers.IDirectoryService directoryService) - { - return Task.FromResult(true); - } - - [IgnoreDataMember] - public override bool SupportsPeople - { - get - { - return false; - } - } - } -} diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs deleted file mode 100644 index 97b96127a2..0000000000 --- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs +++ /dev/null @@ -1,1778 +0,0 @@ -using MediaBrowser.Controller.Channels; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.Movies; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.Playlists; -using MediaBrowser.Controller.TV; -using MediaBrowser.Model.Channels; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.LiveTv; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Querying; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Dto; -using MediaBrowser.Model.Extensions; - -namespace MediaBrowser.Controller.Entities -{ - public class UserViewBuilder - { - private readonly IChannelManager _channelManager; - private readonly ILiveTvManager _liveTvManager; - private readonly IUserViewManager _userViewManager; - private readonly ILibraryManager _libraryManager; - private readonly ILogger _logger; - private readonly IUserDataManager _userDataManager; - private readonly ITVSeriesManager _tvSeriesManager; - private readonly IServerConfigurationManager _config; - private readonly IPlaylistManager _playlistManager; - - public UserViewBuilder(IUserViewManager userViewManager, ILiveTvManager liveTvManager, IChannelManager channelManager, ILibraryManager libraryManager, ILogger logger, IUserDataManager userDataManager, ITVSeriesManager tvSeriesManager, IServerConfigurationManager config, IPlaylistManager playlistManager) - { - _userViewManager = userViewManager; - _liveTvManager = liveTvManager; - _channelManager = channelManager; - _libraryManager = libraryManager; - _logger = logger; - _userDataManager = userDataManager; - _tvSeriesManager = tvSeriesManager; - _config = config; - _playlistManager = playlistManager; - } - - public async Task<QueryResult<BaseItem>> GetUserItems(Folder queryParent, Folder displayParent, string viewType, InternalItemsQuery query) - { - var user = query.User; - - //if (query.IncludeItemTypes != null && - // query.IncludeItemTypes.Length == 1 && - // string.Equals(query.IncludeItemTypes[0], "Playlist", StringComparison.OrdinalIgnoreCase)) - //{ - // if (!string.Equals(viewType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase)) - // { - // return await FindPlaylists(queryParent, user, query).ConfigureAwait(false); - // } - //} - - switch (viewType) - { - case CollectionType.Channels: - { - var result = await _channelManager.GetChannelsInternal(new ChannelQuery - { - UserId = user == null ? null : user.Id.ToString("N"), - Limit = query.Limit, - StartIndex = query.StartIndex - - }, CancellationToken.None).ConfigureAwait(false); - - return GetResult(result); - } - - case SpecialFolder.LiveTvChannels: - { - var result = _liveTvManager.GetInternalChannels(new LiveTvChannelQuery - { - UserId = query.User.Id.ToString("N"), - Limit = query.Limit, - StartIndex = query.StartIndex - - }, new DtoOptions(), CancellationToken.None); - - return GetResult(result); - } - - case SpecialFolder.LiveTvNowPlaying: - { - var result = _liveTvManager.GetRecommendedProgramsInternal(new RecommendedProgramQuery - { - UserId = query.User.Id.ToString("N"), - Limit = query.Limit, - IsAiring = true - - }, new Dto.DtoOptions(), CancellationToken.None); - - return GetResult(result); - } - - case SpecialFolder.LiveTvRecordingGroups: - { - var result = await _liveTvManager.GetInternalRecordings(new RecordingQuery - { - UserId = query.User.Id.ToString("N"), - Status = RecordingStatus.Completed, - Limit = query.Limit, - StartIndex = query.StartIndex - - }, new DtoOptions(), CancellationToken.None).ConfigureAwait(false); - - return GetResult(result); - } - - case CollectionType.LiveTv: - { - return await GetLiveTvView(queryParent, user, query).ConfigureAwait(false); - } - - case CollectionType.Photos: - case CollectionType.Books: - case CollectionType.HomeVideos: - case CollectionType.Games: - case CollectionType.MusicVideos: - { - if (query.Recursive) - { - query.Recursive = true; - query.Parent = queryParent; - query.SetUser(user); - - return _libraryManager.GetItemsResult(query); - } - return GetResult(queryParent.GetChildren(user, true), queryParent, query); - } - - case CollectionType.Folders: - return GetResult(user.RootFolder.GetChildren(user, true), queryParent, query); - - case CollectionType.Playlists: - return GetPlaylistsView(queryParent, user, query); - - case CollectionType.BoxSets: - return GetBoxsetView(queryParent, user, query); - - case CollectionType.TvShows: - return GetTvView(queryParent, user, query); - - case CollectionType.Movies: - return GetMovieFolders(queryParent, user, query); - - case SpecialFolder.TvShowSeries: - return GetTvSeries(queryParent, user, query); - - case SpecialFolder.TvGenres: - return GetTvGenres(queryParent, user, query); - - case SpecialFolder.TvGenre: - return GetTvGenreItems(queryParent, displayParent, user, query); - - case SpecialFolder.TvResume: - return GetTvResume(queryParent, user, query); - - case SpecialFolder.TvNextUp: - return GetTvNextUp(queryParent, query); - - case SpecialFolder.TvLatest: - return GetTvLatest(queryParent, user, query); - - case SpecialFolder.MovieFavorites: - return GetFavoriteMovies(queryParent, user, query); - - case SpecialFolder.MovieLatest: - return GetMovieLatest(queryParent, user, query); - - case SpecialFolder.MovieGenres: - return GetMovieGenres(queryParent, user, query); - - case SpecialFolder.MovieGenre: - return GetMovieGenreItems(queryParent, displayParent, user, query); - - case SpecialFolder.MovieResume: - return GetMovieResume(queryParent, user, query); - - case SpecialFolder.MovieMovies: - return GetMovieMovies(queryParent, user, query); - - case SpecialFolder.MovieCollections: - return GetMovieCollections(queryParent, user, query); - - case SpecialFolder.TvFavoriteEpisodes: - return GetFavoriteEpisodes(queryParent, user, query); - - case SpecialFolder.TvFavoriteSeries: - return GetFavoriteSeries(queryParent, user, query); - - case CollectionType.Music: - return GetMusicFolders(queryParent, user, query); - - case SpecialFolder.MusicGenres: - return GetMusicGenres(queryParent, user, query); - - case SpecialFolder.MusicLatest: - return GetMusicLatest(queryParent, user, query); - - case SpecialFolder.MusicPlaylists: - return GetMusicPlaylists(queryParent, user, query); - - case SpecialFolder.MusicAlbums: - return GetMusicAlbums(queryParent, user, query); - - case SpecialFolder.MusicAlbumArtists: - return GetMusicAlbumArtists(queryParent, user, query); - - case SpecialFolder.MusicArtists: - return GetMusicArtists(queryParent, user, query); - - case SpecialFolder.MusicSongs: - return GetMusicSongs(queryParent, user, query); - - case SpecialFolder.MusicFavorites: - return GetMusicFavorites(queryParent, user, query); - - case SpecialFolder.MusicFavoriteAlbums: - return GetFavoriteAlbums(queryParent, user, query); - - case SpecialFolder.MusicFavoriteArtists: - return GetFavoriteArtists(queryParent, user, query); - - case SpecialFolder.MusicFavoriteSongs: - return GetFavoriteSongs(queryParent, user, query); - - default: - { - if (queryParent is UserView) - { - return GetResult(GetMediaFolders(user).OfType<Folder>().SelectMany(i => i.GetChildren(user, true)), queryParent, query); - } - return GetResult(queryParent.GetChildren(user, true), queryParent, query); - } - } - } - - private QueryResult<BaseItem> GetMusicFolders(Folder parent, User user, InternalItemsQuery query) - { - if (query.Recursive) - { - query.Recursive = true; - query.SetUser(user); - - if (query.IncludeItemTypes.Length == 0) - { - query.IncludeItemTypes = new[] { typeof(MusicArtist).Name, typeof(MusicAlbum).Name, typeof(Audio.Audio).Name, typeof(MusicVideo).Name }; - } - - return parent.QueryRecursive(query); - } - - var list = new List<BaseItem>(); - - 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 QueryResult<BaseItem> GetMusicFavorites(Folder parent, User user, InternalItemsQuery query) - { - var list = new List<BaseItem>(); - - 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); - } - - private QueryResult<BaseItem> GetMusicGenres(Folder parent, User user, InternalItemsQuery query) - { - var result = _libraryManager.GetMusicGenres(new InternalItemsQuery(user) - { - AncestorIds = new[] { parent.Id.ToString("N") }, - StartIndex = query.StartIndex, - Limit = query.Limit - }); - - return new QueryResult<BaseItem> - { - TotalRecordCount = result.TotalRecordCount, - Items = result.Items.Select(i => i.Item1).ToArray() - }; - } - - private QueryResult<BaseItem> GetMusicAlbumArtists(Folder parent, User user, InternalItemsQuery query) - { - var artists = _libraryManager.GetAlbumArtists(new InternalItemsQuery(user) - { - AncestorIds = new[] { parent.Id.ToString("N") }, - StartIndex = query.StartIndex, - Limit = query.Limit - }); - - return new QueryResult<BaseItem> - { - TotalRecordCount = artists.TotalRecordCount, - Items = artists.Items.Select(i => i.Item1).ToArray() - }; - } - - private QueryResult<BaseItem> GetMusicArtists(Folder parent, User user, InternalItemsQuery query) - { - var artists = _libraryManager.GetArtists(new InternalItemsQuery(user) - { - AncestorIds = new[] { parent.Id.ToString("N") }, - StartIndex = query.StartIndex, - Limit = query.Limit - }); - - return new QueryResult<BaseItem> - { - TotalRecordCount = artists.TotalRecordCount, - Items = artists.Items.Select(i => i.Item1).ToArray() - }; - } - - private QueryResult<BaseItem> GetFavoriteArtists(Folder parent, User user, InternalItemsQuery query) - { - var artists = _libraryManager.GetArtists(new InternalItemsQuery(user) - { - AncestorIds = new[] { parent.Id.ToString("N") }, - StartIndex = query.StartIndex, - Limit = query.Limit, - IsFavorite = true - }); - - return new QueryResult<BaseItem> - { - TotalRecordCount = artists.TotalRecordCount, - Items = artists.Items.Select(i => i.Item1).ToArray() - }; - } - - private QueryResult<BaseItem> GetMusicPlaylists(Folder parent, User user, InternalItemsQuery query) - { - query.Parent = null; - query.IncludeItemTypes = new[] { typeof(Playlist).Name }; - query.SetUser(user); - query.Recursive = true; - - return _libraryManager.GetItemsResult(query); - } - - private QueryResult<BaseItem> GetMusicAlbums(Folder parent, User user, InternalItemsQuery query) - { - query.Recursive = true; - query.Parent = parent; - query.SetUser(user); - - query.IncludeItemTypes = new[] { typeof(MusicAlbum).Name }; - - return _libraryManager.GetItemsResult(query); - } - - private QueryResult<BaseItem> GetMusicSongs(Folder parent, User user, InternalItemsQuery query) - { - query.Recursive = true; - query.Parent = parent; - query.SetUser(user); - - query.IncludeItemTypes = new[] { typeof(Audio.Audio).Name }; - - return _libraryManager.GetItemsResult(query); - } - - private QueryResult<BaseItem> GetMusicLatest(Folder parent, User user, InternalItemsQuery query) - { - var items = _userViewManager.GetLatestItems(new LatestItemsQuery - { - UserId = user.Id.ToString("N"), - Limit = GetSpecialItemsLimit(), - IncludeItemTypes = new[] { typeof(Audio.Audio).Name }, - ParentId = parent == null ? null : parent.Id.ToString("N"), - GroupItems = true - - }, query.DtoOptions).Select(i => i.Item1 ?? i.Item2.FirstOrDefault()).Where(i => i != null); - - query.OrderBy = new Tuple<string, SortOrder>[] { }; - - return PostFilterAndSort(items, parent, null, query, false, true); - } - - private QueryResult<BaseItem> GetFavoriteSongs(Folder parent, User user, InternalItemsQuery query) - { - query.Recursive = true; - query.Parent = parent; - query.SetUser(user); - query.IsFavorite = true; - query.IncludeItemTypes = new[] { typeof(Audio.Audio).Name }; - - return _libraryManager.GetItemsResult(query); - } - - private QueryResult<BaseItem> GetFavoriteAlbums(Folder parent, User user, InternalItemsQuery query) - { - query.Recursive = true; - query.Parent = parent; - query.SetUser(user); - query.IsFavorite = true; - query.IncludeItemTypes = new[] { typeof(MusicAlbum).Name }; - - return _libraryManager.GetItemsResult(query); - } - - private int GetSpecialItemsLimit() - { - return 50; - } - - private QueryResult<BaseItem> GetMovieFolders(Folder parent, User user, InternalItemsQuery query) - { - if (query.Recursive) - { - query.Recursive = true; - query.SetUser(user); - - if (query.IncludeItemTypes.Length == 0) - { - query.IncludeItemTypes = new[] { typeof(Movie).Name, typeof(BoxSet).Name }; - } - - return parent.QueryRecursive(query); - } - - var list = new List<BaseItem>(); - - 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); - } - - private QueryResult<BaseItem> GetFavoriteMovies(Folder parent, User user, InternalItemsQuery query) - { - query.Recursive = true; - query.Parent = parent; - query.SetUser(user); - query.IsFavorite = true; - query.IncludeItemTypes = new[] { typeof(Movie).Name }; - - return _libraryManager.GetItemsResult(query); - } - - private QueryResult<BaseItem> GetFavoriteSeries(Folder parent, User user, InternalItemsQuery query) - { - query.Recursive = true; - query.Parent = parent; - query.SetUser(user); - query.IsFavorite = true; - query.IncludeItemTypes = new[] { typeof(Series).Name }; - - return _libraryManager.GetItemsResult(query); - } - - private QueryResult<BaseItem> GetFavoriteEpisodes(Folder parent, User user, InternalItemsQuery query) - { - query.Recursive = true; - query.Parent = parent; - query.SetUser(user); - query.IsFavorite = true; - query.IncludeItemTypes = new[] { typeof(Episode).Name }; - - return _libraryManager.GetItemsResult(query); - } - - private QueryResult<BaseItem> GetMovieMovies(Folder parent, User user, InternalItemsQuery query) - { - query.Recursive = true; - query.Parent = parent; - query.SetUser(user); - - query.IncludeItemTypes = new[] { typeof(Movie).Name }; - - return _libraryManager.GetItemsResult(query); - } - - private QueryResult<BaseItem> GetMovieCollections(Folder parent, User user, InternalItemsQuery query) - { - return GetBoxsetView(parent, user, query); - } - - private QueryResult<BaseItem> GetMovieLatest(Folder parent, User user, InternalItemsQuery query) - { - query.OrderBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }.Select(i => new Tuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(); - - query.Recursive = true; - query.Parent = parent; - query.SetUser(user); - query.Limit = GetSpecialItemsLimit(); - query.IncludeItemTypes = new[] { typeof(Movie).Name }; - - return ConvertToResult(_libraryManager.GetItemList(query)); - } - - private QueryResult<BaseItem> GetMovieResume(Folder parent, User user, InternalItemsQuery query) - { - query.OrderBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName }.Select(i => new Tuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(); - query.IsResumable = true; - query.Recursive = true; - query.Parent = parent; - query.SetUser(user); - query.Limit = GetSpecialItemsLimit(); - query.IncludeItemTypes = new[] { typeof(Movie).Name }; - - return ConvertToResult(_libraryManager.GetItemList(query)); - } - - private QueryResult<BaseItem> ConvertToResult(List<BaseItem> items) - { - var arr = items.ToArray(); - return new QueryResult<BaseItem> - { - Items = arr, - TotalRecordCount = arr.Length - }; - } - - private QueryResult<BaseItem> GetMovieGenres(Folder parent, User user, InternalItemsQuery query) - { - var genres = parent.QueryRecursive(new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(Movie).Name }, - Recursive = true, - EnableTotalRecordCount = false - - }).Items - .SelectMany(i => i.Genres) - .DistinctNames() - .Select(i => - { - try - { - return _libraryManager.GetGenre(i); - } - catch - { - // Full exception logged at lower levels - _logger.Error("Error getting genre"); - return null; - } - - }) - .Where(i => i != null) - .Select(i => GetUserViewWithName(i.Name, SpecialFolder.MovieGenre, i.SortName, parent)); - - return GetResult(genres, parent, query); - } - - private QueryResult<BaseItem> GetMovieGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query) - { - query.Recursive = true; - query.Parent = queryParent; - query.GenreIds = new[] { displayParent.Id.ToString("N") }; - query.SetUser(user); - - query.IncludeItemTypes = new[] { typeof(Movie).Name }; - - return _libraryManager.GetItemsResult(query); - } - - private QueryResult<BaseItem> GetPlaylistsView(Folder parent, User user, InternalItemsQuery query) - { - return GetResult(_playlistManager.GetPlaylists(user.Id.ToString("N")), parent, query); - } - - private QueryResult<BaseItem> GetBoxsetView(Folder parent, User user, InternalItemsQuery query) - { - query.Parent = null; - query.IncludeItemTypes = new[] { typeof(BoxSet).Name }; - query.SetUser(user); - query.Recursive = true; - - return _libraryManager.GetItemsResult(query); - } - - private QueryResult<BaseItem> GetTvView(Folder parent, User user, InternalItemsQuery query) - { - if (query.Recursive) - { - query.Recursive = true; - query.SetUser(user); - - if (query.IncludeItemTypes.Length == 0) - { - query.IncludeItemTypes = new[] { typeof(Series).Name, typeof(Season).Name, typeof(Episode).Name }; - } - - return parent.QueryRecursive(query); - } - - var list = new List<BaseItem>(); - - 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); - } - - private QueryResult<BaseItem> GetTvLatest(Folder parent, User user, InternalItemsQuery query) - { - query.OrderBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName }.Select(i => new Tuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(); - - query.Recursive = true; - query.Parent = parent; - query.SetUser(user); - query.Limit = GetSpecialItemsLimit(); - query.IncludeItemTypes = new[] { typeof(Episode).Name }; - query.IsVirtualItem = false; - - return ConvertToResult(_libraryManager.GetItemList(query)); - } - - private QueryResult<BaseItem> GetTvNextUp(Folder parent, InternalItemsQuery query) - { - var parentFolders = GetMediaFolders(parent, query.User, new[] { CollectionType.TvShows, string.Empty }); - - var result = _tvSeriesManager.GetNextUp(new NextUpQuery - { - Limit = query.Limit, - StartIndex = query.StartIndex, - UserId = query.User.Id.ToString("N") - - }, parentFolders, query.DtoOptions); - - return result; - } - - private QueryResult<BaseItem> GetTvResume(Folder parent, User user, InternalItemsQuery query) - { - query.OrderBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName }.Select(i => new Tuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(); - query.IsResumable = true; - query.Recursive = true; - query.Parent = parent; - query.SetUser(user); - query.Limit = GetSpecialItemsLimit(); - query.IncludeItemTypes = new[] { typeof(Episode).Name }; - - return ConvertToResult(_libraryManager.GetItemList(query)); - } - - private QueryResult<BaseItem> GetTvSeries(Folder parent, User user, InternalItemsQuery query) - { - query.Recursive = true; - query.Parent = parent; - query.SetUser(user); - - query.IncludeItemTypes = new[] { typeof(Series).Name }; - - return _libraryManager.GetItemsResult(query); - } - - private QueryResult<BaseItem> GetTvGenres(Folder parent, User user, InternalItemsQuery query) - { - var genres = parent.QueryRecursive(new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(Series).Name }, - Recursive = true, - EnableTotalRecordCount = false - - }).Items - .SelectMany(i => i.Genres) - .DistinctNames() - .Select(i => - { - try - { - return _libraryManager.GetGenre(i); - } - catch - { - // Full exception logged at lower levels - _logger.Error("Error getting genre"); - return null; - } - - }) - .Where(i => i != null) - .Select(i => GetUserViewWithName(i.Name, SpecialFolder.TvGenre, i.SortName, parent)); - - return GetResult(genres, parent, query); - } - - private QueryResult<BaseItem> GetTvGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query) - { - query.Recursive = true; - query.Parent = queryParent; - query.GenreIds = new[] { displayParent.Id.ToString("N") }; - query.SetUser(user); - - query.IncludeItemTypes = new[] { typeof(Series).Name }; - - return _libraryManager.GetItemsResult(query); - } - - private QueryResult<BaseItem> GetResult<T>(QueryResult<T> result) - where T : BaseItem - { - return new QueryResult<BaseItem> - { - Items = result.Items, - TotalRecordCount = result.TotalRecordCount - }; - } - - private QueryResult<BaseItem> GetResult<T>(IEnumerable<T> items, - BaseItem queryParent, - InternalItemsQuery query) - where T : BaseItem - { - items = items.Where(i => Filter(i, query.User, query, _userDataManager, _libraryManager)); - - return PostFilterAndSort(items, queryParent, null, query, _libraryManager, _config, true, true); - } - - public static bool FilterItem(BaseItem item, InternalItemsQuery query) - { - return Filter(item, query.User, query, BaseItem.UserDataManager, BaseItem.LibraryManager); - } - - private QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, - BaseItem queryParent, - int? totalRecordLimit, - InternalItemsQuery query, - bool collapseBoxSetItems, - bool enableSorting) - { - return PostFilterAndSort(items, queryParent, totalRecordLimit, query, _libraryManager, _config, collapseBoxSetItems, enableSorting); - } - - public static QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, - BaseItem queryParent, - int? totalRecordLimit, - InternalItemsQuery query, - ILibraryManager libraryManager, - IServerConfigurationManager configurationManager, - bool collapseBoxSetItems, - bool enableSorting) - { - var user = query.User; - - items = FilterVirtualEpisodes(items, - query.IsMissing, - query.IsUnaired); - - if (collapseBoxSetItems && user != null) - { - items = CollapseBoxSetItemsIfNeeded(items, query, queryParent, user, configurationManager); - } - - // This must be the last filter - if (!string.IsNullOrEmpty(query.AdjacentTo)) - { - items = FilterForAdjacency(items.ToList(), query.AdjacentTo); - } - - return SortAndPage(items, totalRecordLimit, query, libraryManager, enableSorting); - } - - public static IEnumerable<BaseItem> CollapseBoxSetItemsIfNeeded(IEnumerable<BaseItem> items, - InternalItemsQuery query, - BaseItem queryParent, - User user, - IServerConfigurationManager configurationManager) - { - if (items == null) - { - throw new ArgumentNullException("items"); - } - - if (CollapseBoxSetItems(query, queryParent, user, configurationManager)) - { - items = BaseItem.CollectionManager.CollapseItemsWithinBoxSets(items, user); - } - - items = ApplyPostCollectionCollapseFilters(query, items, user); - - return items; - } - - private static IEnumerable<BaseItem> ApplyPostCollectionCollapseFilters(InternalItemsQuery request, - IEnumerable<BaseItem> items, - User user) - { - if (!string.IsNullOrEmpty(request.NameStartsWithOrGreater)) - { - items = items.Where(i => string.Compare(request.NameStartsWithOrGreater, i.SortName, StringComparison.CurrentCultureIgnoreCase) < 1); - } - if (!string.IsNullOrEmpty(request.NameStartsWith)) - { - items = items.Where(i => string.Compare(request.NameStartsWith, i.SortName.Substring(0, 1), StringComparison.CurrentCultureIgnoreCase) == 0); - } - - if (!string.IsNullOrEmpty(request.NameLessThan)) - { - items = items.Where(i => string.Compare(request.NameLessThan, i.SortName, StringComparison.CurrentCultureIgnoreCase) == 1); - } - - return items; - } - - public static bool CollapseBoxSetItems(InternalItemsQuery query, - BaseItem queryParent, - User user, - IServerConfigurationManager configurationManager) - { - // Could end up stuck in a loop like this - if (queryParent is BoxSet) - { - return false; - } - - var param = query.CollapseBoxSetItems; - - if (!param.HasValue) - { - if (user != null && !configurationManager.Configuration.EnableGroupingIntoCollections) - { - return false; - } - - if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains("Movie", StringComparer.OrdinalIgnoreCase)) - { - param = true; - } - } - - return param.HasValue && param.Value && AllowBoxSetCollapsing(query); - } - - private static bool AllowBoxSetCollapsing(InternalItemsQuery request) - { - if (request.IsFavorite.HasValue) - { - return false; - } - if (request.IsFavoriteOrLiked.HasValue) - { - return false; - } - if (request.IsLiked.HasValue) - { - return false; - } - if (request.IsPlayed.HasValue) - { - return false; - } - if (request.IsResumable.HasValue) - { - return false; - } - if (request.IsFolder.HasValue) - { - return false; - } - - if (request.Genres.Length > 0) - { - return false; - } - - if (request.GenreIds.Length > 0) - { - return false; - } - - if (request.HasImdbId.HasValue) - { - return false; - } - - if (request.HasOfficialRating.HasValue) - { - return false; - } - - if (request.HasOverview.HasValue) - { - return false; - } - - if (request.HasParentalRating.HasValue) - { - return false; - } - - if (request.HasSpecialFeature.HasValue) - { - return false; - } - - if (request.HasSubtitles.HasValue) - { - return false; - } - - if (request.HasThemeSong.HasValue) - { - return false; - } - - if (request.HasThemeVideo.HasValue) - { - return false; - } - - if (request.HasTmdbId.HasValue) - { - return false; - } - - if (request.HasTrailer.HasValue) - { - return false; - } - - if (request.ImageTypes.Length > 0) - { - return false; - } - - if (request.Is3D.HasValue) - { - return false; - } - - if (request.IsHD.HasValue) - { - return false; - } - - if (request.IsInBoxSet.HasValue) - { - return false; - } - - if (request.IsLocked.HasValue) - { - return false; - } - - if (request.IsPlaceHolder.HasValue) - { - return false; - } - - if (request.IsPlayed.HasValue) - { - return false; - } - - if (!string.IsNullOrWhiteSpace(request.Person)) - { - return false; - } - - if (request.PersonIds.Length > 0) - { - return false; - } - - if (request.ItemIds.Length > 0) - { - return false; - } - - if (request.StudioIds.Length > 0) - { - return false; - } - - if (request.GenreIds.Length > 0) - { - return false; - } - - if (request.VideoTypes.Length > 0) - { - return false; - } - - if (request.Years.Length > 0) - { - return false; - } - - if (request.Tags.Length > 0) - { - return false; - } - - if (request.OfficialRatings.Length > 0) - { - return false; - } - - if (request.MinPlayers.HasValue) - { - return false; - } - - if (request.MaxPlayers.HasValue) - { - return false; - } - - if (request.MinCommunityRating.HasValue) - { - return false; - } - - if (request.MinCriticRating.HasValue) - { - return false; - } - - if (request.MinIndexNumber.HasValue) - { - return false; - } - - return true; - } - - private static IEnumerable<BaseItem> FilterVirtualEpisodes( - IEnumerable<BaseItem> items, - bool? isMissing, - bool? isUnaired) - { - if (isMissing.HasValue) - { - var val = isMissing.Value; - items = items.Where(i => - { - var e = i as Episode; - if (e != null) - { - return e.IsMissingEpisode == val; - } - return true; - }); - } - - if (isUnaired.HasValue) - { - var val = isUnaired.Value; - items = items.Where(i => - { - var e = i as Episode; - if (e != null) - { - return e.IsUnaired == val; - } - return true; - }); - } - - return items; - } - - public static QueryResult<BaseItem> SortAndPage(IEnumerable<BaseItem> items, - int? totalRecordLimit, - InternalItemsQuery query, - ILibraryManager libraryManager, bool enableSorting) - { - items = items.DistinctBy(i => i.GetPresentationUniqueKey(), StringComparer.OrdinalIgnoreCase); - - if (query.OrderBy.Length > 0) - { - items = libraryManager.Sort(items, query.User, query.OrderBy); - } - - var itemsArray = totalRecordLimit.HasValue ? items.Take(totalRecordLimit.Value).ToArray() : items.ToArray(); - var totalCount = itemsArray.Length; - - if (query.Limit.HasValue) - { - itemsArray = itemsArray.Skip(query.StartIndex ?? 0).Take(query.Limit.Value).ToArray(); - } - else if (query.StartIndex.HasValue) - { - itemsArray = itemsArray.Skip(query.StartIndex.Value).ToArray(); - } - - return new QueryResult<BaseItem> - { - TotalRecordCount = totalCount, - Items = itemsArray - }; - } - - public static bool Filter(BaseItem item, User user, InternalItemsQuery query, IUserDataManager userDataManager, ILibraryManager libraryManager) - { - if (query.ItemIdsFromPersonFilters == null) - { - if (query.PersonIds.Length > 0) - { - var names = query.PersonIds - .Select(libraryManager.GetItemById) - .Select(i => i == null ? null : i.Name) - .Where(i => !string.IsNullOrWhiteSpace(i)) - .ToList(); - - var itemIdList = new List<Guid>(); - foreach (var name in names) - { - itemIdList.AddRange(libraryManager.GetItemIds(new InternalItemsQuery - { - Person = name - })); - } - query.ItemIdsFromPersonFilters = itemIdList; - } - - // Apply person filter - else if (!string.IsNullOrWhiteSpace(query.Person)) - { - var itemIdList = new List<Guid>(); - - itemIdList.AddRange(libraryManager.GetItemIds(new InternalItemsQuery - { - Person = query.Person, - PersonTypes = query.PersonTypes - })); - query.ItemIdsFromPersonFilters = itemIdList; - } - } - - if (query.MediaTypes.Length > 0 && !query.MediaTypes.Contains(item.MediaType ?? string.Empty, StringComparer.OrdinalIgnoreCase)) - { - return false; - } - - if (query.IncludeItemTypes.Length > 0 && !query.IncludeItemTypes.Contains(item.GetClientTypeName(), StringComparer.OrdinalIgnoreCase)) - { - return false; - } - - if (query.ExcludeItemTypes.Length > 0 && query.ExcludeItemTypes.Contains(item.GetClientTypeName(), StringComparer.OrdinalIgnoreCase)) - { - return false; - } - - if (query.IsVirtualItem.HasValue && item.IsVirtualItem != query.IsVirtualItem.Value) - { - return false; - } - - if (query.IsFolder.HasValue && query.IsFolder.Value != item.IsFolder) - { - return false; - } - - UserItemData userData = null; - - if (query.IsLiked.HasValue) - { - userData = userData ?? userDataManager.GetUserData(user, item); - - if (!userData.Likes.HasValue || userData.Likes != query.IsLiked.Value) - { - return false; - } - } - - if (query.IsFavoriteOrLiked.HasValue) - { - userData = userData ?? userDataManager.GetUserData(user, item); - var isFavoriteOrLiked = userData.IsFavorite || (userData.Likes ?? false); - - if (isFavoriteOrLiked != query.IsFavoriteOrLiked.Value) - { - return false; - } - } - - if (query.IsFavorite.HasValue) - { - userData = userData ?? userDataManager.GetUserData(user, item); - - if (userData.IsFavorite != query.IsFavorite.Value) - { - return false; - } - } - - if (query.IsResumable.HasValue) - { - userData = userData ?? userDataManager.GetUserData(user, item); - var isResumable = userData.PlaybackPositionTicks > 0; - - if (isResumable != query.IsResumable.Value) - { - return false; - } - } - - if (query.IsPlayed.HasValue) - { - if (item.IsPlayed(user) != query.IsPlayed.Value) - { - return false; - } - } - - if (query.IsInBoxSet.HasValue) - { - var val = query.IsInBoxSet.Value; - if (item.GetParents().OfType<BoxSet>().Any() != val) - { - return false; - } - } - - // Filter by Video3DFormat - if (query.Is3D.HasValue) - { - var val = query.Is3D.Value; - var video = item as Video; - - if (video == null || val != video.Video3DFormat.HasValue) - { - return false; - } - } - - if (query.IsHD.HasValue) - { - var val = query.IsHD.Value; - var video = item as Video; - - if (video == null || !video.IsHD.HasValue || val != video.IsHD) - { - return false; - } - } - - if (query.IsLocked.HasValue) - { - var val = query.IsLocked.Value; - if (item.IsLocked != val) - { - return false; - } - } - - if (query.HasOverview.HasValue) - { - var filterValue = query.HasOverview.Value; - - var hasValue = !string.IsNullOrEmpty(item.Overview); - - if (hasValue != filterValue) - { - return false; - } - } - - if (query.HasImdbId.HasValue) - { - var filterValue = query.HasImdbId.Value; - - var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Imdb)); - - if (hasValue != filterValue) - { - return false; - } - } - - if (query.HasTmdbId.HasValue) - { - var filterValue = query.HasTmdbId.Value; - - var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Tmdb)); - - if (hasValue != filterValue) - { - return false; - } - } - - if (query.HasTvdbId.HasValue) - { - var filterValue = query.HasTvdbId.Value; - - var hasValue = !string.IsNullOrEmpty(item.GetProviderId(MetadataProviders.Tvdb)); - - if (hasValue != filterValue) - { - return false; - } - } - - if (query.HasOfficialRating.HasValue) - { - var filterValue = query.HasOfficialRating.Value; - - var hasValue = !string.IsNullOrEmpty(item.OfficialRating); - - if (hasValue != filterValue) - { - return false; - } - } - - if (query.IsPlaceHolder.HasValue) - { - var filterValue = query.IsPlaceHolder.Value; - - var isPlaceHolder = false; - - var hasPlaceHolder = item as ISupportsPlaceHolders; - - if (hasPlaceHolder != null) - { - isPlaceHolder = hasPlaceHolder.IsPlaceHolder; - } - - if (isPlaceHolder != filterValue) - { - return false; - } - } - - if (query.HasSpecialFeature.HasValue) - { - var filterValue = query.HasSpecialFeature.Value; - - var movie = item as IHasSpecialFeatures; - - if (movie != null) - { - var ok = filterValue - ? movie.SpecialFeatureIds.Length > 0 - : movie.SpecialFeatureIds.Length == 0; - - if (!ok) - { - return false; - } - } - else - { - return false; - } - } - - if (query.HasSubtitles.HasValue) - { - var val = query.HasSubtitles.Value; - - var video = item as Video; - - if (video == null || val != video.HasSubtitles) - { - return false; - } - } - - if (query.HasParentalRating.HasValue) - { - var val = query.HasParentalRating.Value; - - var rating = item.CustomRating; - - if (string.IsNullOrEmpty(rating)) - { - rating = item.OfficialRating; - } - - if (val) - { - if (string.IsNullOrEmpty(rating)) - { - return false; - } - } - else - { - if (!string.IsNullOrEmpty(rating)) - { - return false; - } - } - } - - if (query.HasTrailer.HasValue) - { - var val = query.HasTrailer.Value; - var trailerCount = 0; - - var hasTrailers = item as IHasTrailers; - if (hasTrailers != null) - { - trailerCount = hasTrailers.GetTrailerIds().Count; - } - - var ok = val ? trailerCount > 0 : trailerCount == 0; - - if (!ok) - { - return false; - } - } - - if (query.HasThemeSong.HasValue) - { - var filterValue = query.HasThemeSong.Value; - - var themeCount = item.ThemeSongIds.Length; - var ok = filterValue ? themeCount > 0 : themeCount == 0; - - if (!ok) - { - return false; - } - } - - if (query.HasThemeVideo.HasValue) - { - var filterValue = query.HasThemeVideo.Value; - - var themeCount = item.ThemeVideoIds.Length; - var ok = filterValue ? themeCount > 0 : themeCount == 0; - - if (!ok) - { - return false; - } - } - - // Apply genre filter - if (query.Genres.Length > 0 && !query.Genres.Any(v => item.Genres.Contains(v, StringComparer.OrdinalIgnoreCase))) - { - return false; - } - - // Filter by VideoType - if (query.VideoTypes.Length > 0) - { - var video = item as Video; - if (video == null || !query.VideoTypes.Contains(video.VideoType)) - { - return false; - } - } - - if (query.ImageTypes.Length > 0 && !query.ImageTypes.Any(item.HasImage)) - { - return false; - } - - // Apply studio filter - if (query.StudioIds.Length > 0 && !query.StudioIds.Any(id => - { - var studioItem = libraryManager.GetItemById(id); - return studioItem != null && item.Studios.Contains(studioItem.Name, StringComparer.OrdinalIgnoreCase); - })) - { - return false; - } - - // Apply genre filter - if (query.GenreIds.Length > 0 && !query.GenreIds.Any(id => - { - var genreItem = libraryManager.GetItemById(id); - return genreItem != null && item.Genres.Contains(genreItem.Name, StringComparer.OrdinalIgnoreCase); - })) - { - return false; - } - - // Apply year filter - if (query.Years.Length > 0) - { - if (!(item.ProductionYear.HasValue && query.Years.Contains(item.ProductionYear.Value))) - { - return false; - } - } - - // Apply official rating filter - if (query.OfficialRatings.Length > 0 && !query.OfficialRatings.Contains(item.OfficialRating ?? string.Empty)) - { - return false; - } - - if (query.ItemIds.Length > 0) - { - if (!query.ItemIds.Contains(item.Id.ToString("N"), StringComparer.OrdinalIgnoreCase)) - { - return false; - } - } - - // Apply person filter - if (query.ItemIdsFromPersonFilters != null) - { - if (!query.ItemIdsFromPersonFilters.Contains(item.Id)) - { - return false; - } - } - - // Apply tag filter - var tags = query.Tags; - if (tags.Length > 0) - { - if (!tags.Any(v => item.Tags.Contains(v, StringComparer.OrdinalIgnoreCase))) - { - return false; - } - } - - if (query.MinPlayers.HasValue) - { - var filterValue = query.MinPlayers.Value; - - var game = item as Game; - - if (game != null) - { - var players = game.PlayersSupported ?? 1; - - var ok = players >= filterValue; - - if (!ok) - { - return false; - } - } - else - { - return false; - } - } - - if (query.MaxPlayers.HasValue) - { - var filterValue = query.MaxPlayers.Value; - - var game = item as Game; - - if (game != null) - { - var players = game.PlayersSupported ?? 1; - - var ok = players <= filterValue; - - if (!ok) - { - return false; - } - } - else - { - return false; - } - } - - if (query.MinCommunityRating.HasValue) - { - var val = query.MinCommunityRating.Value; - - if (!(item.CommunityRating.HasValue && item.CommunityRating >= val)) - { - return false; - } - } - - if (query.MinCriticRating.HasValue) - { - var val = query.MinCriticRating.Value; - - if (!(item.CriticRating.HasValue && item.CriticRating >= val)) - { - return false; - } - } - - if (query.MinIndexNumber.HasValue) - { - var val = query.MinIndexNumber.Value; - - if (!(item.IndexNumber.HasValue && item.IndexNumber.Value >= val)) - { - return false; - } - } - - if (query.MinPremiereDate.HasValue) - { - var val = query.MinPremiereDate.Value; - - if (!(item.PremiereDate.HasValue && item.PremiereDate.Value >= val)) - { - return false; - } - } - - if (query.MaxPremiereDate.HasValue) - { - var val = query.MaxPremiereDate.Value; - - if (!(item.PremiereDate.HasValue && item.PremiereDate.Value <= val)) - { - return false; - } - } - - if (query.ParentIndexNumber.HasValue) - { - var filterValue = query.ParentIndexNumber.Value; - - if (item.ParentIndexNumber.HasValue && item.ParentIndexNumber.Value != filterValue) - { - return false; - } - } - - if (query.SeriesStatuses.Length > 0) - { - var ok = new[] { item }.OfType<Series>().Any(p => p.Status.HasValue && query.SeriesStatuses.Contains(p.Status.Value)); - if (!ok) - { - return false; - } - } - - if (query.AiredDuringSeason.HasValue) - { - var episode = item as Episode; - - if (episode == null) - { - return false; - } - - if (!Series.FilterEpisodesBySeason(new[] { episode }, query.AiredDuringSeason.Value, true).Any()) - { - return false; - } - } - - return true; - } - - private IEnumerable<BaseItem> GetMediaFolders(User user) - { - if (user == null) - { - return _libraryManager.RootFolder - .Children - .OfType<Folder>() - .Where(UserView.IsEligibleForGrouping); - } - return user.RootFolder - .GetChildren(user, true) - .OfType<Folder>() - .Where(i => user.IsFolderGrouped(i.Id) && UserView.IsEligibleForGrouping(i)); - } - - private List<BaseItem> GetMediaFolders(User user, IEnumerable<string> viewTypes) - { - if (user == null) - { - return GetMediaFolders(null) - .Where(i => - { - var folder = i as ICollectionFolder; - - return folder != null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase); - }).ToList(); - } - return GetMediaFolders(user) - .Where(i => - { - var folder = i as ICollectionFolder; - - return folder != null && viewTypes.Contains(folder.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase); - }).ToList(); - } - - private List<BaseItem> GetMediaFolders(Folder parent, User user, IEnumerable<string> viewTypes) - { - if (parent == null || parent is UserView) - { - return GetMediaFolders(user, viewTypes); - } - - return new List<BaseItem> { parent }; - } - - private async Task<QueryResult<BaseItem>> GetLiveTvView(Folder queryParent, User user, InternalItemsQuery query) - { - if (query.Recursive) - { - return await _liveTvManager.GetInternalRecordings(new RecordingQuery - { - IsInProgress = false, - Status = RecordingStatus.Completed, - UserId = user.Id.ToString("N") - - }, new DtoOptions(), CancellationToken.None).ConfigureAwait(false); - } - - var list = new List<BaseItem>(); - - //list.Add(await GetUserSubView(SpecialFolder.LiveTvNowPlaying, user, "0", parent).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 UserView GetUserViewWithName(string name, string type, string sortName, BaseItem parent) - { - return _userViewManager.GetUserSubView(name, parent.Id.ToString("N"), type, sortName, CancellationToken.None); - } - - private UserView GetUserView(string type, string localizationKey, string sortName, BaseItem parent) - { - return _userViewManager.GetUserSubView(parent.Id.ToString("N"), type, localizationKey, sortName, CancellationToken.None); - } - - public static IEnumerable<BaseItem> FilterForAdjacency(List<BaseItem> list, string adjacentToId) - { - var adjacentToIdGuid = new Guid(adjacentToId); - var adjacentToItem = list.FirstOrDefault(i => i.Id == adjacentToIdGuid); - - var index = list.IndexOf(adjacentToItem); - - var previousId = Guid.Empty; - var nextId = Guid.Empty; - - if (index > 0) - { - previousId = list[index - 1].Id; - } - - if (index < list.Count - 1) - { - nextId = list[index + 1].Id; - } - - return list.Where(i => i.Id == previousId || i.Id == nextId || i.Id == adjacentToIdGuid); - } - } -} diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs deleted file mode 100644 index dca1cfd01b..0000000000 --- a/MediaBrowser.Controller/Entities/Video.cs +++ /dev/null @@ -1,806 +0,0 @@ -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.Dto; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.MediaInfo; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.Extensions; - -using MediaBrowser.Controller.Channels; -using MediaBrowser.Controller.IO; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.Extensions; - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Class Video - /// </summary> - public class Video : BaseItem, - IHasAspectRatio, - ISupportsPlaceHolders, - IHasMediaSources - { - [IgnoreDataMember] - public string PrimaryVersionId { get; set; } - - public string[] AdditionalParts { get; set; } - public string[] LocalAlternateVersions { get; set; } - public LinkedChild[] LinkedAlternateVersions { get; set; } - - [IgnoreDataMember] - public override bool SupportsPlayedStatus - { - get - { - return true; - } - } - - [IgnoreDataMember] - public override bool SupportsPeople - { - get { return true; } - } - - [IgnoreDataMember] - public override bool SupportsInheritedParentImages - { - get - { - return true; - } - } - - [IgnoreDataMember] - public override bool SupportsPositionTicksResume - { - get - { - var extraType = ExtraType; - if (extraType.HasValue) - { - if (extraType.Value == Model.Entities.ExtraType.Sample) - { - return false; - } - if (extraType.Value == Model.Entities.ExtraType.ThemeVideo) - { - return false; - } - if (extraType.Value == Model.Entities.ExtraType.Trailer) - { - return false; - } - } - return true; - } - } - - public void SetPrimaryVersionId(string id) - { - if (string.IsNullOrWhiteSpace(id)) - { - PrimaryVersionId = null; - } - else - { - PrimaryVersionId = id; - } - - PresentationUniqueKey = CreatePresentationUniqueKey(); - } - - public override string CreatePresentationUniqueKey() - { - if (!string.IsNullOrWhiteSpace(PrimaryVersionId)) - { - return PrimaryVersionId; - } - - return base.CreatePresentationUniqueKey(); - } - - [IgnoreDataMember] - public override bool EnableRefreshOnDateModifiedChange - { - get - { - return VideoType == VideoType.VideoFile || VideoType == VideoType.Iso; - } - } - - [IgnoreDataMember] - public override bool SupportsThemeMedia - { - get { return true; } - } - - /// <summary> - /// Gets or sets the timestamp. - /// </summary> - /// <value>The timestamp.</value> - public TransportStreamTimestamp? Timestamp { get; set; } - - /// <summary> - /// Gets or sets the subtitle paths. - /// </summary> - /// <value>The subtitle paths.</value> - public string[] SubtitleFiles { get; set; } - - /// <summary> - /// Gets or sets a value indicating whether this instance has subtitles. - /// </summary> - /// <value><c>true</c> if this instance has subtitles; otherwise, <c>false</c>.</value> - public bool HasSubtitles { get; set; } - - public bool IsPlaceHolder { get; set; } - public bool IsShortcut { get; set; } - public string ShortcutPath { get; set; } - - /// <summary> - /// Gets or sets the default index of the video stream. - /// </summary> - /// <value>The default index of the video stream.</value> - public int? DefaultVideoStreamIndex { get; set; } - - /// <summary> - /// Gets or sets the type of the video. - /// </summary> - /// <value>The type of the video.</value> - public VideoType VideoType { get; set; } - - /// <summary> - /// Gets or sets the type of the iso. - /// </summary> - /// <value>The type of the iso.</value> - public IsoType? IsoType { get; set; } - - /// <summary> - /// Gets or sets the video3 D format. - /// </summary> - /// <value>The video3 D format.</value> - public Video3DFormat? Video3DFormat { get; set; } - - public string[] GetPlayableStreamFileNames() - { - var videoType = VideoType; - - if (videoType == VideoType.Iso && IsoType == Model.Entities.IsoType.BluRay) - { - videoType = VideoType.BluRay; - } - else if (videoType == VideoType.Iso && IsoType == Model.Entities.IsoType.Dvd) - { - videoType = VideoType.Dvd; - } - else - { - return new string[] { }; - } - return MediaEncoder.GetPlayableStreamFileNames(Path, videoType); - } - - /// <summary> - /// Gets or sets the aspect ratio. - /// </summary> - /// <value>The aspect ratio.</value> - public string AspectRatio { get; set; } - - public Video() - { - AdditionalParts = EmptyStringArray; - LocalAlternateVersions = EmptyStringArray; - SubtitleFiles = EmptyStringArray; - LinkedAlternateVersions = EmptyLinkedChildArray; - } - - public override bool CanDownload() - { - if (VideoType == VideoType.Dvd || VideoType == VideoType.BluRay) - { - return false; - } - - var locationType = LocationType; - return locationType != LocationType.Remote && - locationType != LocationType.Virtual; - } - - [IgnoreDataMember] - public override bool SupportsAddingToPlaylist - { - get { return true; } - } - - [IgnoreDataMember] - public int MediaSourceCount - { - get - { - if (!string.IsNullOrWhiteSpace(PrimaryVersionId)) - { - var item = LibraryManager.GetItemById(PrimaryVersionId) as Video; - if (item != null) - { - return item.MediaSourceCount; - } - } - return LinkedAlternateVersions.Length + LocalAlternateVersions.Length + 1; - } - } - - [IgnoreDataMember] - public bool IsStacked - { - get { return AdditionalParts.Length > 0; } - } - - [IgnoreDataMember] - public bool HasLocalAlternateVersions - { - get { return LocalAlternateVersions.Length > 0; } - } - - public IEnumerable<Guid> GetAdditionalPartIds() - { - return AdditionalParts.Select(i => LibraryManager.GetNewItemId(i, typeof(Video))); - } - - public IEnumerable<Guid> GetLocalAlternateVersionIds() - { - return LocalAlternateVersions.Select(i => LibraryManager.GetNewItemId(i, typeof(Video))); - } - - [IgnoreDataMember] - public override SourceType SourceType - { - get - { - if (IsActiveRecording()) - { - return SourceType.LiveTV; - } - - return base.SourceType; - } - } - - protected bool IsActiveRecording() - { - return LiveTvManager.GetActiveRecordingInfo(Path) != null; - } - - public override bool CanDelete() - { - if (IsActiveRecording()) - { - return false; - } - - return base.CanDelete(); - } - - [IgnoreDataMember] - public bool IsCompleteMedia - { - get { return !IsActiveRecording(); } - } - - [IgnoreDataMember] - protected virtual bool EnableDefaultVideoUserDataKeys - { - get - { - return true; - } - } - - public override List<string> GetUserDataKeys() - { - var list = base.GetUserDataKeys(); - - if (EnableDefaultVideoUserDataKeys) - { - if (ExtraType.HasValue) - { - var key = this.GetProviderId(MetadataProviders.Tmdb); - if (!string.IsNullOrWhiteSpace(key)) - { - list.Insert(0, GetUserDataKey(key)); - } - - key = this.GetProviderId(MetadataProviders.Imdb); - if (!string.IsNullOrWhiteSpace(key)) - { - list.Insert(0, GetUserDataKey(key)); - } - } - else - { - var key = this.GetProviderId(MetadataProviders.Imdb); - if (!string.IsNullOrWhiteSpace(key)) - { - list.Insert(0, key); - } - - key = this.GetProviderId(MetadataProviders.Tmdb); - if (!string.IsNullOrWhiteSpace(key)) - { - list.Insert(0, key); - } - } - } - - return list; - } - - private string GetUserDataKey(string providerId) - { - var key = providerId + "-" + ExtraType.ToString().ToLower(); - - // Make sure different trailers have their own data. - if (RunTimeTicks.HasValue) - { - key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture); - } - - return key; - } - - public IEnumerable<Video> GetLinkedAlternateVersions() - { - return LinkedAlternateVersions - .Select(GetLinkedChild) - .Where(i => i != null) - .OfType<Video>() - .OrderBy(i => i.SortName); - } - - /// <summary> - /// Gets the additional parts. - /// </summary> - /// <returns>IEnumerable{Video}.</returns> - public IEnumerable<Video> GetAdditionalParts() - { - return GetAdditionalPartIds() - .Select(i => LibraryManager.GetItemById(i)) - .Where(i => i != null) - .OfType<Video>() - .OrderBy(i => i.SortName); - } - - [IgnoreDataMember] - public override string ContainingFolderPath - { - get - { - if (IsStacked) - { - return FileSystem.GetDirectoryName(Path); - } - - if (!IsPlaceHolder) - { - if (VideoType == VideoType.BluRay || VideoType == VideoType.Dvd) - { - return Path; - } - } - - return base.ContainingFolderPath; - } - } - - [IgnoreDataMember] - public override string FileNameWithoutExtension - { - get - { - if (LocationType == LocationType.FileSystem) - { - if (VideoType == VideoType.BluRay || VideoType == VideoType.Dvd) - { - return System.IO.Path.GetFileName(Path); - } - - return System.IO.Path.GetFileNameWithoutExtension(Path); - } - - return null; - } - } - - internal override ItemUpdateType UpdateFromResolvedItem(BaseItem newItem) - { - var updateType = base.UpdateFromResolvedItem(newItem); - - var newVideo = newItem as Video; - if (newVideo != null) - { - if (!AdditionalParts.SequenceEqual(newVideo.AdditionalParts, StringComparer.Ordinal)) - { - AdditionalParts = newVideo.AdditionalParts; - updateType |= ItemUpdateType.MetadataImport; - } - if (!LocalAlternateVersions.SequenceEqual(newVideo.LocalAlternateVersions, StringComparer.Ordinal)) - { - LocalAlternateVersions = newVideo.LocalAlternateVersions; - updateType |= ItemUpdateType.MetadataImport; - } - if (VideoType != newVideo.VideoType) - { - VideoType = newVideo.VideoType; - updateType |= ItemUpdateType.MetadataImport; - } - } - - return updateType; - } - - public static string[] QueryPlayableStreamFiles(string rootPath, VideoType videoType) - { - if (videoType == VideoType.Dvd) - { - return FileSystem.GetFiles(rootPath, new[] { ".vob" }, false, true) - .OrderByDescending(i => i.Length) - .ThenBy(i => i.FullName) - .Take(1) - .Select(i => i.FullName) - .ToArray(); - } - if (videoType == VideoType.BluRay) - { - return FileSystem.GetFiles(rootPath, new[] { ".m2ts" }, false, true) - .OrderByDescending(i => i.Length) - .ThenBy(i => i.FullName) - .Take(1) - .Select(i => i.FullName) - .ToArray(); - } - return new string[] { }; - } - - /// <summary> - /// Gets a value indicating whether [is3 D]. - /// </summary> - /// <value><c>true</c> if [is3 D]; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public bool Is3D - { - get { return Video3DFormat.HasValue; } - } - - /// <summary> - /// Gets the type of the media. - /// </summary> - /// <value>The type of the media.</value> - [IgnoreDataMember] - public override string MediaType - { - get - { - return Model.Entities.MediaType.Video; - } - } - - protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken) - { - var hasChanges = await base.RefreshedOwnedItems(options, fileSystemChildren, cancellationToken).ConfigureAwait(false); - - if (IsStacked) - { - var tasks = AdditionalParts - .Select(i => RefreshMetadataForOwnedVideo(options, true, i, cancellationToken)); - - await Task.WhenAll(tasks).ConfigureAwait(false); - } - - // Must have a parent to have additional parts or alternate versions - // In other words, it must be part of the Parent/Child tree - // The additional parts won't have additional parts themselves - if (LocationType == LocationType.FileSystem && GetParent() != null) - { - if (!IsStacked) - { - RefreshLinkedAlternateVersions(); - - var tasks = LocalAlternateVersions - .Select(i => RefreshMetadataForOwnedVideo(options, false, i, cancellationToken)); - - await Task.WhenAll(tasks).ConfigureAwait(false); - } - } - - return hasChanges; - } - - private void RefreshLinkedAlternateVersions() - { - foreach (var child in LinkedAlternateVersions) - { - // Reset the cached value - if (child.ItemId.HasValue && child.ItemId.Value == Guid.Empty) - { - child.ItemId = null; - } - } - } - - public override void UpdateToRepository(ItemUpdateType updateReason, CancellationToken cancellationToken) - { - base.UpdateToRepository(updateReason, cancellationToken); - - var localAlternates = GetLocalAlternateVersionIds() - .Select(i => LibraryManager.GetItemById(i)) - .Where(i => i != null); - - foreach (var item in localAlternates) - { - item.ImageInfos = ImageInfos; - item.Overview = Overview; - item.ProductionYear = ProductionYear; - item.PremiereDate = PremiereDate; - item.CommunityRating = CommunityRating; - item.OfficialRating = OfficialRating; - item.Genres = Genres; - item.ProviderIds = ProviderIds; - - item.UpdateToRepository(ItemUpdateType.MetadataDownload, cancellationToken); - } - } - - public override IEnumerable<FileSystemMetadata> GetDeletePaths() - { - if (!IsInMixedFolder) - { - return new[] { - new FileSystemMetadata - { - FullName = ContainingFolderPath, - IsDirectory = true - } - }; - } - - return base.GetDeletePaths(); - } - - public List<MediaStream> GetMediaStreams() - { - return MediaSourceManager.GetMediaStreams(new MediaStreamQuery - { - ItemId = Id - }); - } - - public virtual MediaStream GetDefaultVideoStream() - { - if (!DefaultVideoStreamIndex.HasValue) - { - return null; - } - - return MediaSourceManager.GetMediaStreams(new MediaStreamQuery - { - ItemId = Id, - Index = DefaultVideoStreamIndex.Value - - }).FirstOrDefault(); - } - - private List<Tuple<Video, MediaSourceType>> GetAllVideosForMediaSources() - { - var list = new List<Tuple<Video, MediaSourceType>>(); - - list.Add(new Tuple<Video, MediaSourceType>(this, MediaSourceType.Default)); - list.AddRange(GetLinkedAlternateVersions().Select(i => new Tuple<Video, MediaSourceType>(i, MediaSourceType.Grouping))); - - if (!string.IsNullOrWhiteSpace(PrimaryVersionId)) - { - var primary = LibraryManager.GetItemById(PrimaryVersionId) as Video; - if (primary != null) - { - var existingIds = list.Select(i => i.Item1.Id).ToList(); - list.Add(new Tuple<Video, MediaSourceType>(primary, MediaSourceType.Grouping)); - list.AddRange(primary.GetLinkedAlternateVersions().Where(i => !existingIds.Contains(i.Id)).Select(i => new Tuple<Video, MediaSourceType>(i, MediaSourceType.Grouping))); - } - } - - var localAlternates = list - .SelectMany(i => i.Item1.GetLocalAlternateVersionIds()) - .Select(LibraryManager.GetItemById) - .Where(i => i != null) - .OfType<Video>() - .ToList(); - - list.AddRange(localAlternates.Select(i => new Tuple<Video, MediaSourceType>(i, MediaSourceType.Default))); - - return list; - } - - public virtual List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution) - { - if (SourceType == SourceType.Channel) - { - var sources = ChannelManager.GetStaticMediaSources(this, CancellationToken.None) - .ToList(); - - if (sources.Count > 0) - { - return sources; - } - - return new List<MediaSourceInfo> - { - GetVersionInfo(enablePathSubstitution, this, MediaSourceType.Placeholder) - }; - } - - var list = GetAllVideosForMediaSources(); - var result = list.Select(i => GetVersionInfo(enablePathSubstitution, i.Item1, i.Item2)).ToList(); - - if (IsActiveRecording()) - { - foreach (var mediaSource in result) - { - mediaSource.Type = MediaSourceType.Placeholder; - } - } - - return result.OrderBy(i => - { - if (i.VideoType == VideoType.VideoFile) - { - return 0; - } - - return 1; - - }).ThenBy(i => i.Video3DFormat.HasValue ? 1 : 0) - .ThenByDescending(i => - { - var stream = i.VideoStream; - - return stream == null || stream.Width == null ? 0 : stream.Width.Value; - }) - .ToList(); - } - - private static MediaSourceInfo GetVersionInfo(bool enablePathSubstitution, Video media, MediaSourceType type) - { - if (media == null) - { - throw new ArgumentNullException("media"); - } - - var locationType = media.LocationType; - - var info = new MediaSourceInfo - { - Id = media.Id.ToString("N"), - IsoType = media.IsoType, - Protocol = locationType == LocationType.Remote ? MediaProtocol.Http : MediaProtocol.File, - MediaStreams = MediaSourceManager.GetMediaStreams(media.Id), - Name = GetMediaSourceName(media), - Path = enablePathSubstitution ? GetMappedPath(media, media.Path, locationType) : media.Path, - RunTimeTicks = media.RunTimeTicks, - Video3DFormat = media.Video3DFormat, - VideoType = media.VideoType, - Container = media.Container, - Size = media.Size, - Timestamp = media.Timestamp, - Type = type, - SupportsDirectStream = media.VideoType == VideoType.VideoFile, - IsRemote = media.IsShortcut - }; - - if (info.Protocol == MediaProtocol.File) - { - info.ETag = media.DateModified.Ticks.ToString(CultureInfo.InvariantCulture).GetMD5().ToString("N"); - } - - if (media.IsShortcut) - { - info.Path = media.ShortcutPath; - - if (!string.IsNullOrWhiteSpace(info.Path)) - { - if (info.Path.StartsWith("Http", StringComparison.OrdinalIgnoreCase)) - { - info.Protocol = MediaProtocol.Http; - info.SupportsDirectStream = false; - } - else if (info.Path.StartsWith("Rtmp", StringComparison.OrdinalIgnoreCase)) - { - info.Protocol = MediaProtocol.Rtmp; - info.SupportsDirectStream = false; - } - else if (info.Path.StartsWith("Rtsp", StringComparison.OrdinalIgnoreCase)) - { - info.Protocol = MediaProtocol.Rtsp; - info.SupportsDirectStream = false; - } - else - { - info.Protocol = MediaProtocol.File; - } - } - } - - if (string.IsNullOrEmpty(info.Container)) - { - if (media.VideoType == VideoType.VideoFile || media.VideoType == VideoType.Iso) - { - if (!string.IsNullOrWhiteSpace(media.Path) && locationType != LocationType.Remote && locationType != LocationType.Virtual) - { - info.Container = System.IO.Path.GetExtension(media.Path).TrimStart('.'); - } - } - } - - info.Bitrate = media.TotalBitrate; - info.InferTotalBitrate(); - - return info; - } - - private static string GetMediaSourceName(Video video) - { - var terms = new List<string>(); - - var locationType = video.LocationType; - var path = video.Path; - if ((locationType == LocationType.FileSystem || locationType == LocationType.Offline) && !string.IsNullOrWhiteSpace(path)) - { - terms.Add(System.IO.Path.GetFileName(path)); - } - else - { - terms.Add(video.Name); - } - - if (video.Video3DFormat.HasValue) - { - terms.Add("3D"); - } - - if (video.VideoType == VideoType.BluRay) - { - terms.Add("Bluray"); - } - else if (video.VideoType == VideoType.Dvd) - { - terms.Add("DVD"); - } - else if (video.VideoType == VideoType.Iso) - { - if (video.IsoType.HasValue) - { - if (video.IsoType.Value == Model.Entities.IsoType.BluRay) - { - terms.Add("Bluray"); - } - else if (video.IsoType.Value == Model.Entities.IsoType.Dvd) - { - terms.Add("DVD"); - } - } - else - { - terms.Add("ISO"); - } - } - - return string.Join("/", terms.ToArray(terms.Count)); - } - - } -} diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs deleted file mode 100644 index 49b967104e..0000000000 --- a/MediaBrowser.Controller/Entities/Year.cs +++ /dev/null @@ -1,160 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using MediaBrowser.Model.Serialization; - -namespace MediaBrowser.Controller.Entities -{ - /// <summary> - /// Class Year - /// </summary> - public class Year : BaseItem, IItemByName - { - public override List<string> GetUserDataKeys() - { - var list = base.GetUserDataKeys(); - - list.Insert(0, "Year-" + Name); - return list; - } - - /// <summary> - /// Returns the folder containing the item. - /// If the item is a folder, it returns the folder itself - /// </summary> - /// <value>The containing folder path.</value> - [IgnoreDataMember] - public override string ContainingFolderPath - { - get - { - return Path; - } - } - - public override double? GetDefaultPrimaryImageAspectRatio() - { - double value = 2; - value /= 3; - - return value; - } - - [IgnoreDataMember] - public override bool SupportsAncestors - { - get - { - return false; - } - } - - public override bool CanDelete() - { - return false; - } - - /// <summary> - /// Gets a value indicating whether this instance is owned item. - /// </summary> - /// <value><c>true</c> if this instance is owned item; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public override bool IsOwnedItem - { - get - { - return false; - } - } - - public override bool IsSaveLocalMetadataEnabled() - { - return true; - } - - public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query) - { - int year; - - var usCulture = new CultureInfo("en-US"); - - if (!int.TryParse(Name, NumberStyles.Integer, usCulture, out year)) - { - return new List<BaseItem>(); - } - - query.Years = new[] { year }; - - return LibraryManager.GetItemList(query); - } - - public int? GetYearValue() - { - int i; - - if (int.TryParse(Name, NumberStyles.Integer, CultureInfo.InvariantCulture, out i)) - { - return i; - } - - return null; - } - - [IgnoreDataMember] - public override bool SupportsPeople - { - get - { - return false; - } - } - - public static string GetPath(string name) - { - return GetPath(name, true); - } - - public static string GetPath(string name, bool normalizeName) - { - // Trim the period at the end because windows will have a hard time with that - var validName = normalizeName ? - FileSystem.GetValidFilename(name).Trim().TrimEnd('.') : - name; - - return System.IO.Path.Combine(ConfigurationManager.ApplicationPaths.YearPath, validName); - } - - private string GetRebasedPath() - { - return GetPath(System.IO.Path.GetFileName(Path), false); - } - - public override bool RequiresRefresh() - { - var newPath = GetRebasedPath(); - if (!string.Equals(Path, newPath, StringComparison.Ordinal)) - { - Logger.Debug("{0} path has changed from {1} to {2}", GetType().Name, Path, newPath); - return true; - } - return base.RequiresRefresh(); - } - - /// <summary> - /// This is called before any metadata refresh and returns true or false indicating if changes were made - /// </summary> - public override bool BeforeMetadataRefresh() - { - var hasChanges = base.BeforeMetadataRefresh(); - - var newPath = GetRebasedPath(); - if (!string.Equals(Path, newPath, StringComparison.Ordinal)) - { - Path = newPath; - hasChanges = true; - } - - return hasChanges; - } - } -} |
