aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Controller
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Controller')
-rw-r--r--MediaBrowser.Controller/Channels/Channel.cs2
-rw-r--r--MediaBrowser.Controller/Channels/ChannelAudioItem.cs101
-rw-r--r--MediaBrowser.Controller/Channels/ChannelFolderItem.cs89
-rw-r--r--MediaBrowser.Controller/Channels/ChannelItemInfo.cs8
-rw-r--r--MediaBrowser.Controller/Channels/ChannelMediaInfo.cs2
-rw-r--r--MediaBrowser.Controller/Channels/ChannelVideoItem.cs126
-rw-r--r--MediaBrowser.Controller/Channels/IChannelItem.cs11
-rw-r--r--MediaBrowser.Controller/Channels/IChannelMediaItem.cs18
-rw-r--r--MediaBrowser.Controller/Chapters/IChapterManager.cs2
-rw-r--r--MediaBrowser.Controller/Drawing/IImageProcessor.cs2
-rw-r--r--MediaBrowser.Controller/Drawing/ImageCollageOptions.cs5
-rw-r--r--MediaBrowser.Controller/Dto/IDtoService.cs3
-rw-r--r--MediaBrowser.Controller/Entities/AggregateFolder.cs37
-rw-r--r--MediaBrowser.Controller/Entities/Audio/Audio.cs49
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs64
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicArtist.cs64
-rw-r--r--MediaBrowser.Controller/Entities/Audio/MusicGenre.cs28
-rw-r--r--MediaBrowser.Controller/Entities/BaseItem.cs215
-rw-r--r--MediaBrowser.Controller/Entities/Book.cs30
-rw-r--r--MediaBrowser.Controller/Entities/CollectionFolder.cs87
-rw-r--r--MediaBrowser.Controller/Entities/Folder.cs585
-rw-r--r--MediaBrowser.Controller/Entities/Game.cs17
-rw-r--r--MediaBrowser.Controller/Entities/GameGenre.cs28
-rw-r--r--MediaBrowser.Controller/Entities/GameSystem.cs13
-rw-r--r--MediaBrowser.Controller/Entities/Genre.cs28
-rw-r--r--MediaBrowser.Controller/Entities/IHasImages.cs3
-rw-r--r--MediaBrowser.Controller/Entities/IHasMetadata.cs8
-rw-r--r--MediaBrowser.Controller/Entities/IHasSeries.cs9
-rw-r--r--MediaBrowser.Controller/Entities/IHasTrailers.cs12
-rw-r--r--MediaBrowser.Controller/Entities/IHasUserData.cs14
-rw-r--r--MediaBrowser.Controller/Entities/IItemByName.cs6
-rw-r--r--MediaBrowser.Controller/Entities/InternalItemsQuery.cs44
-rw-r--r--MediaBrowser.Controller/Entities/KeywordExtensions.cs (renamed from MediaBrowser.Controller/Entities/IHasKeywords.cs)12
-rw-r--r--MediaBrowser.Controller/Entities/Movies/BoxSet.cs12
-rw-r--r--MediaBrowser.Controller/Entities/Movies/Movie.cs63
-rw-r--r--MediaBrowser.Controller/Entities/MusicVideo.cs15
-rw-r--r--MediaBrowser.Controller/Entities/Person.cs27
-rw-r--r--MediaBrowser.Controller/Entities/Photo.cs8
-rw-r--r--MediaBrowser.Controller/Entities/PhotoAlbum.cs9
-rw-r--r--MediaBrowser.Controller/Entities/Studio.cs29
-rw-r--r--MediaBrowser.Controller/Entities/TV/Episode.cs141
-rw-r--r--MediaBrowser.Controller/Entities/TV/Season.cs193
-rw-r--r--MediaBrowser.Controller/Entities/TV/Series.cs281
-rw-r--r--MediaBrowser.Controller/Entities/TagExtensions.cs (renamed from MediaBrowser.Controller/Entities/IHasTags.cs)15
-rw-r--r--MediaBrowser.Controller/Entities/Trailer.cs48
-rw-r--r--MediaBrowser.Controller/Entities/User.cs9
-rw-r--r--MediaBrowser.Controller/Entities/UserItemData.cs4
-rw-r--r--MediaBrowser.Controller/Entities/UserRootFolder.cs22
-rw-r--r--MediaBrowser.Controller/Entities/UserView.cs20
-rw-r--r--MediaBrowser.Controller/Entities/UserViewBuilder.cs424
-rw-r--r--MediaBrowser.Controller/Entities/Video.cs293
-rw-r--r--MediaBrowser.Controller/Entities/Year.cs27
-rw-r--r--MediaBrowser.Controller/Health/IHealthMonitor.cs12
-rw-r--r--MediaBrowser.Controller/IServerApplicationHost.cs11
-rw-r--r--MediaBrowser.Controller/Library/ILibraryManager.cs57
-rw-r--r--MediaBrowser.Controller/Library/IUserDataManager.cs21
-rw-r--r--MediaBrowser.Controller/Library/TVUtils.cs2
-rw-r--r--MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs7
-rw-r--r--MediaBrowser.Controller/LiveTv/ChannelInfo.cs4
-rw-r--r--MediaBrowser.Controller/LiveTv/IListingsProvider.cs1
-rw-r--r--MediaBrowser.Controller/LiveTv/ILiveTvManager.cs20
-rw-r--r--MediaBrowser.Controller/LiveTv/ILiveTvService.cs19
-rw-r--r--MediaBrowser.Controller/LiveTv/ITunerHost.cs2
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs11
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvChannel.cs20
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvProgram.cs49
-rw-r--r--MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs26
-rw-r--r--MediaBrowser.Controller/LiveTv/TimerEventInfo.cs14
-rw-r--r--MediaBrowser.Controller/LiveTv/TunerChannelMapping.cs16
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj20
-rw-r--r--MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs8
-rw-r--r--MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs33
-rw-r--r--MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs10
-rw-r--r--MediaBrowser.Controller/Net/IHttpResultFactory.cs10
-rw-r--r--MediaBrowser.Controller/Notifications/INotificationsRepository.cs6
-rw-r--r--MediaBrowser.Controller/Persistence/IDisplayPreferencesRepository.cs6
-rw-r--r--MediaBrowser.Controller/Persistence/IItemRepository.cs20
-rw-r--r--MediaBrowser.Controller/Persistence/IUserDataRepository.cs8
-rw-r--r--MediaBrowser.Controller/Playlists/Playlist.cs74
-rw-r--r--MediaBrowser.Controller/Providers/BaseItemXmlParser.cs27
-rw-r--r--MediaBrowser.Controller/Providers/DirectoryService.cs6
-rw-r--r--MediaBrowser.Controller/Providers/EpisodeInfo.cs3
-rw-r--r--MediaBrowser.Controller/Providers/IHasItemChangeMonitor.cs3
-rw-r--r--MediaBrowser.Controller/Providers/IItemIdentityConverter.cs4
-rw-r--r--MediaBrowser.Controller/Providers/IItemIdentityProvider.cs4
-rw-r--r--MediaBrowser.Controller/Providers/IProviderManager.cs22
-rw-r--r--MediaBrowser.Controller/Providers/IProviderRepository.cs31
-rw-r--r--MediaBrowser.Controller/Providers/ISeriesOrderManager.cs11
-rw-r--r--MediaBrowser.Controller/Providers/ISeriesOrderProvider.cs10
-rw-r--r--MediaBrowser.Controller/Providers/ItemIdentifier.cs36
-rw-r--r--MediaBrowser.Controller/Providers/ItemIdentities.cs16
-rw-r--r--MediaBrowser.Controller/Providers/ItemInfo.cs8
-rw-r--r--MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs3
-rw-r--r--MediaBrowser.Controller/Providers/MetadataStatus.cs49
-rw-r--r--MediaBrowser.Controller/Session/ISessionManager.cs3
-rw-r--r--MediaBrowser.Controller/Subtitles/SubtitleSearchRequest.cs1
96 files changed, 1954 insertions, 2132 deletions
diff --git a/MediaBrowser.Controller/Channels/Channel.cs b/MediaBrowser.Controller/Channels/Channel.cs
index 43f7b6637..718a0d878 100644
--- a/MediaBrowser.Controller/Channels/Channel.cs
+++ b/MediaBrowser.Controller/Channels/Channel.cs
@@ -38,7 +38,7 @@ namespace MediaBrowser.Controller.Channels
set { }
}
- public override async Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
+ protected override async Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query)
{
try
{
diff --git a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
deleted file mode 100644
index 41e9dd203..000000000
--- a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs
+++ /dev/null
@@ -1,101 +0,0 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Model.Channels;
-using MediaBrowser.Model.Configuration;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using System.Collections.Generic;
-using System.Linq;
-using System.Runtime.Serialization;
-using System.Threading;
-
-namespace MediaBrowser.Controller.Channels
-{
- public class ChannelAudioItem : Audio
- {
- public ChannelMediaContentType ContentType { get; set; }
-
- public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
-
- public override UnratedItem GetBlockUnratedType()
- {
- return UnratedItem.ChannelContent;
- }
-
- protected override string CreateUserDataKey()
- {
- return ExternalId;
- }
-
- [IgnoreDataMember]
- public override bool SupportsLocalMetadata
- {
- get
- {
- return false;
- }
- }
-
- public override bool IsSaveLocalMetadataEnabled()
- {
- return false;
- }
-
- public ChannelAudioItem()
- {
- ChannelMediaSources = new List<ChannelMediaInfo>();
- }
-
- [IgnoreDataMember]
- public override LocationType LocationType
- {
- get
- {
- if (string.IsNullOrEmpty(Path))
- {
- return LocationType.Remote;
- }
-
- return base.LocationType;
- }
- }
-
- protected override string GetInternalMetadataPath(string basePath)
- {
- return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N"));
- }
-
- public override IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
- {
- var sources = ChannelManager.GetStaticMediaSources(this, false, CancellationToken.None)
- .Result.ToList();
-
- if (sources.Count > 0)
- {
- return sources;
- }
-
- var list = base.GetMediaSources(enablePathSubstitution).ToList();
-
- foreach (var mediaSource in list)
- {
- if (string.IsNullOrWhiteSpace(mediaSource.Path))
- {
- mediaSource.Type = MediaSourceType.Placeholder;
- }
- }
-
- return list;
- }
-
- public override bool CanDelete()
- {
- return false;
- }
-
- public override bool IsVisibleStandalone(User user)
- {
- return IsVisibleStandaloneInternal(user, false) && ChannelVideoItem.IsChannelVisible(this, user);
- }
- }
-}
diff --git a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
deleted file mode 100644
index da5d60863..000000000
--- a/MediaBrowser.Controller/Channels/ChannelFolderItem.cs
+++ /dev/null
@@ -1,89 +0,0 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Model.Channels;
-using MediaBrowser.Model.Querying;
-using MediaBrowser.Model.Users;
-using System;
-using System.Runtime.Serialization;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Model.Configuration;
-
-namespace MediaBrowser.Controller.Channels
-{
- public class ChannelFolderItem : Folder
- {
- public ChannelFolderType ChannelFolderType { get; set; }
-
- protected override bool GetBlockUnratedValue(UserPolicy config)
- {
- // Don't block.
- return false;
- }
-
- public override UnratedItem GetBlockUnratedType()
- {
- return UnratedItem.ChannelContent;
- }
-
- [IgnoreDataMember]
- public override bool SupportsLocalMetadata
- {
- get
- {
- return false;
- }
- }
-
- public override bool IsSaveLocalMetadataEnabled()
- {
- return false;
- }
-
- protected override string CreateUserDataKey()
- {
- return ExternalId;
- }
-
- public override async Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
- {
- try
- {
- // Don't blow up here because it could cause parent screens with other content to fail
- return await ChannelManager.GetChannelItemsInternal(new ChannelItemQuery
- {
- ChannelId = ChannelId,
- FolderId = Id.ToString("N"),
- Limit = query.Limit,
- StartIndex = query.StartIndex,
- UserId = query.User.Id.ToString("N"),
- SortBy = query.SortBy,
- SortOrder = query.SortOrder
-
- }, new Progress<double>(), CancellationToken.None);
- }
- catch
- {
- // Already logged at lower levels
- return new QueryResult<BaseItem>
- {
-
- };
- }
- }
-
- protected override string GetInternalMetadataPath(string basePath)
- {
- return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N"));
- }
-
- public override bool CanDelete()
- {
- return false;
- }
-
- public override bool IsVisibleStandalone(User user)
- {
- return IsVisibleStandaloneInternal(user, false) && ChannelVideoItem.IsChannelVisible(this, user);
- }
- }
-}
diff --git a/MediaBrowser.Controller/Channels/ChannelItemInfo.cs b/MediaBrowser.Controller/Channels/ChannelItemInfo.cs
index 587023ab4..57c2f1f7f 100644
--- a/MediaBrowser.Controller/Channels/ChannelItemInfo.cs
+++ b/MediaBrowser.Controller/Channels/ChannelItemInfo.cs
@@ -53,6 +53,12 @@ namespace MediaBrowser.Controller.Channels
public bool IsInfiniteStream { get; set; }
+ public string HomePageUrl { get; set; }
+
+ public List<string> Artists { get; set; }
+
+ public List<string> AlbumArtists { get; set; }
+
public ChannelItemInfo()
{
MediaSources = new List<ChannelMediaInfo>();
@@ -62,6 +68,8 @@ namespace MediaBrowser.Controller.Channels
People = new List<PersonInfo>();
Tags = new List<string>();
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+ Artists = new List<string>();
+ AlbumArtists = new List<string>();
}
}
}
diff --git a/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs b/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs
index 1672b75fa..9424568b4 100644
--- a/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs
+++ b/MediaBrowser.Controller/Channels/ChannelMediaInfo.cs
@@ -65,7 +65,7 @@ namespace MediaBrowser.Controller.Channels
Name = id,
Id = id,
ReadAtNativeFramerate = ReadAtNativeFramerate,
- SupportsDirectStream = Protocol == MediaProtocol.File || Protocol == MediaProtocol.Http,
+ SupportsDirectStream = Protocol == MediaProtocol.File,
SupportsDirectPlay = SupportsDirectPlay
};
diff --git a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
deleted file mode 100644
index 9fe04812e..000000000
--- a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs
+++ /dev/null
@@ -1,126 +0,0 @@
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Model.Channels;
-using MediaBrowser.Model.Configuration;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using System.Runtime.Serialization;
-using System.Threading;
-
-namespace MediaBrowser.Controller.Channels
-{
- public class ChannelVideoItem : Video
- {
- public ChannelMediaContentType ContentType { get; set; }
-
- public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
-
- protected override string CreateUserDataKey()
- {
- if (ContentType == ChannelMediaContentType.MovieExtra)
- {
- var key = this.GetProviderId(MetadataProviders.Imdb) ?? this.GetProviderId(MetadataProviders.Tmdb);
-
- if (!string.IsNullOrWhiteSpace(key))
- {
- key = key + "-" + ExtraType.ToString().ToLower();
-
- // Make sure different trailers have their own data.
- if (RunTimeTicks.HasValue)
- {
- key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture);
- }
-
- return key;
- }
- }
-
- return ExternalId;
- }
-
- public override UnratedItem GetBlockUnratedType()
- {
- return UnratedItem.ChannelContent;
- }
-
- [IgnoreDataMember]
- public override bool SupportsLocalMetadata
- {
- get
- {
- return false;
- }
- }
-
- public override bool IsSaveLocalMetadataEnabled()
- {
- return false;
- }
-
- public ChannelVideoItem()
- {
- ChannelMediaSources = new List<ChannelMediaInfo>();
- }
-
- [IgnoreDataMember]
- public override LocationType LocationType
- {
- get
- {
- if (string.IsNullOrEmpty(Path))
- {
- return LocationType.Remote;
- }
-
- return base.LocationType;
- }
- }
-
- public override IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
- {
- var sources = ChannelManager.GetStaticMediaSources(this, false, CancellationToken.None)
- .Result.ToList();
-
- if (sources.Count > 0)
- {
- return sources;
- }
-
- var list = base.GetMediaSources(enablePathSubstitution).ToList();
-
- foreach (var mediaSource in list)
- {
- if (string.IsNullOrWhiteSpace(mediaSource.Path))
- {
- mediaSource.Type = MediaSourceType.Placeholder;
- }
- }
-
- return list;
- }
-
- protected override string GetInternalMetadataPath(string basePath)
- {
- return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N"));
- }
-
- public override bool CanDelete()
- {
- return false;
- }
-
- public override bool IsVisibleStandalone(User user)
- {
- return IsVisibleStandaloneInternal(user, false) && IsChannelVisible(this, user);
- }
-
- internal static bool IsChannelVisible(BaseItem item, User user)
- {
- var channel = ChannelManager.GetChannel(item.ChannelId);
-
- return channel.IsVisible(user);
- }
- }
-}
diff --git a/MediaBrowser.Controller/Channels/IChannelItem.cs b/MediaBrowser.Controller/Channels/IChannelItem.cs
deleted file mode 100644
index 9b5f0359b..000000000
--- a/MediaBrowser.Controller/Channels/IChannelItem.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using MediaBrowser.Controller.Entities;
-
-namespace MediaBrowser.Controller.Channels
-{
- public interface IChannelItem : IHasImages, IHasTags
- {
- string ChannelId { get; set; }
-
- string ExternalId { get; set; }
- }
-}
diff --git a/MediaBrowser.Controller/Channels/IChannelMediaItem.cs b/MediaBrowser.Controller/Channels/IChannelMediaItem.cs
deleted file mode 100644
index 60a29da90..000000000
--- a/MediaBrowser.Controller/Channels/IChannelMediaItem.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using MediaBrowser.Model.Channels;
-using MediaBrowser.Model.Entities;
-using System.Collections.Generic;
-
-namespace MediaBrowser.Controller.Channels
-{
- public interface IChannelMediaItem : IChannelItem
- {
- long? RunTimeTicks { get; set; }
- string MediaType { get; }
-
- ChannelMediaContentType ContentType { get; set; }
-
- ExtraType? ExtraType { get; set; }
-
- List<ChannelMediaInfo> ChannelMediaSources { get; set; }
- }
-} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Chapters/IChapterManager.cs b/MediaBrowser.Controller/Chapters/IChapterManager.cs
index 676ef9c56..27e06fb8d 100644
--- a/MediaBrowser.Controller/Chapters/IChapterManager.cs
+++ b/MediaBrowser.Controller/Chapters/IChapterManager.cs
@@ -33,7 +33,7 @@ namespace MediaBrowser.Controller.Chapters
/// <param name="chapters">The chapters.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task SaveChapters(string itemId, IEnumerable<ChapterInfo> chapters, CancellationToken cancellationToken);
+ Task SaveChapters(string itemId, List<ChapterInfo> chapters, CancellationToken cancellationToken);
/// <summary>
/// Searches the specified video.
diff --git a/MediaBrowser.Controller/Drawing/IImageProcessor.cs b/MediaBrowser.Controller/Drawing/IImageProcessor.cs
index d42a04f2e..19f391b4a 100644
--- a/MediaBrowser.Controller/Drawing/IImageProcessor.cs
+++ b/MediaBrowser.Controller/Drawing/IImageProcessor.cs
@@ -84,7 +84,7 @@ namespace MediaBrowser.Controller.Drawing
/// </summary>
/// <param name="options">The options.</param>
/// <returns>Task.</returns>
- Task<Tuple<string, string>> ProcessImage(ImageProcessingOptions options);
+ Task<Tuple<string, string, DateTime>> ProcessImage(ImageProcessingOptions options);
/// <summary>
/// Gets the enhanced image.
diff --git a/MediaBrowser.Controller/Drawing/ImageCollageOptions.cs b/MediaBrowser.Controller/Drawing/ImageCollageOptions.cs
index edc4f8558..92a7f5ac9 100644
--- a/MediaBrowser.Controller/Drawing/ImageCollageOptions.cs
+++ b/MediaBrowser.Controller/Drawing/ImageCollageOptions.cs
@@ -23,10 +23,5 @@ namespace MediaBrowser.Controller.Drawing
/// </summary>
/// <value>The height.</value>
public int Height { get; set; }
- /// <summary>
- /// Gets or sets the text.
- /// </summary>
- /// <value>The text.</value>
- public string Text { get; set; }
}
}
diff --git a/MediaBrowser.Controller/Dto/IDtoService.cs b/MediaBrowser.Controller/Dto/IDtoService.cs
index 5f0442f93..e4aa466df 100644
--- a/MediaBrowser.Controller/Dto/IDtoService.cs
+++ b/MediaBrowser.Controller/Dto/IDtoService.cs
@@ -3,6 +3,7 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
using System.Collections.Generic;
+using System.Threading.Tasks;
namespace MediaBrowser.Controller.Dto
{
@@ -68,7 +69,7 @@ namespace MediaBrowser.Controller.Dto
/// <param name="user">The user.</param>
/// <param name="owner">The owner.</param>
/// <returns>IEnumerable&lt;BaseItemDto&gt;.</returns>
- IEnumerable<BaseItemDto> GetBaseItemDtos(IEnumerable<BaseItem> items, DtoOptions options, User user = null,
+ Task<List<BaseItemDto>> GetBaseItemDtos(IEnumerable<BaseItem> items, DtoOptions options, User user = null,
BaseItem owner = null);
/// <summary>
diff --git a/MediaBrowser.Controller/Entities/AggregateFolder.cs b/MediaBrowser.Controller/Entities/AggregateFolder.cs
index 018ff6da0..588a65e98 100644
--- a/MediaBrowser.Controller/Entities/AggregateFolder.cs
+++ b/MediaBrowser.Controller/Entities/AggregateFolder.cs
@@ -64,10 +64,37 @@ namespace MediaBrowser.Controller.Entities
protected override IEnumerable<FileSystemMetadata> GetFileSystemChildren(IDirectoryService directoryService)
{
- return CreateResolveArgs(directoryService).FileSystemChildren;
+ return CreateResolveArgs(directoryService, true).FileSystemChildren;
}
- private ItemResolveArgs CreateResolveArgs(IDirectoryService directoryService)
+ private bool _requiresRefresh;
+ public override bool RequiresRefresh()
+ {
+ var changed = base.RequiresRefresh() || _requiresRefresh;
+
+ if (!changed)
+ {
+ var locations = PhysicalLocations.ToList();
+
+ var newLocations = CreateResolveArgs(new DirectoryService(BaseItem.FileSystem), false).PhysicalLocations.ToList();
+
+ if (!locations.SequenceEqual(newLocations))
+ {
+ changed = true;
+ }
+ }
+
+ return changed;
+ }
+
+ public override bool BeforeMetadataRefresh()
+ {
+ var changed = base.BeforeMetadataRefresh() || _requiresRefresh;
+ _requiresRefresh = false;
+ return changed;
+ }
+
+ private ItemResolveArgs CreateResolveArgs(IDirectoryService directoryService, bool setPhysicalLocations)
{
var path = ContainingFolderPath;
@@ -100,7 +127,11 @@ namespace MediaBrowser.Controller.Entities
args.FileSystemDictionary = fileSystemDictionary;
}
- PhysicalLocationsList = args.PhysicalLocations.ToList();
+ _requiresRefresh = _requiresRefresh || !args.PhysicalLocations.SequenceEqual(PhysicalLocations);
+ if (setPhysicalLocations)
+ {
+ PhysicalLocationsList = args.PhysicalLocations.ToList();
+ }
return args;
}
diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs
index 929308ba0..1897511af 100644
--- a/MediaBrowser.Controller/Entities/Audio/Audio.cs
+++ b/MediaBrowser.Controller/Entities/Audio/Audio.cs
@@ -20,15 +20,12 @@ namespace MediaBrowser.Controller.Entities.Audio
IHasArtist,
IHasMusicGenres,
IHasLookupInfo<SongInfo>,
- IHasTags,
IHasMediaSources,
IThemeMedia,
IArchivable
{
public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
-
- public long? Size { get; set; }
- public string Container { get; set; }
+
public int? TotalBitrate { get; set; }
public ExtraType? ExtraType { get; set; }
@@ -40,12 +37,6 @@ namespace MediaBrowser.Controller.Entities.Audio
public List<string> AlbumArtists { get; set; }
- /// <summary>
- /// Gets or sets the album.
- /// </summary>
- /// <value>The album.</value>
- public string Album { get; set; }
-
[IgnoreDataMember]
public bool IsThemeMedia
{
@@ -55,6 +46,12 @@ namespace MediaBrowser.Controller.Entities.Audio
}
}
+ [IgnoreDataMember]
+ public override bool EnableForceSaveOnDateModifiedChange
+ {
+ get { return true; }
+ }
+
public Audio()
{
Artists = new List<string>();
@@ -150,12 +147,10 @@ namespace MediaBrowser.Controller.Entities.Audio
+ (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name;
}
- /// <summary>
- /// Gets the user data key.
- /// </summary>
- /// <returns>System.String.</returns>
- protected override string CreateUserDataKey()
+ public override List<string> GetUserDataKeys()
{
+ var list = base.GetUserDataKeys();
+
if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys)
{
var songKey = IndexNumber.HasValue ? IndexNumber.Value.ToString("0000") : string.Empty;
@@ -165,7 +160,7 @@ namespace MediaBrowser.Controller.Entities.Audio
{
songKey = ParentIndexNumber.Value.ToString("0000") + "-" + songKey;
}
- songKey+= Name;
+ songKey += Name;
if (!string.IsNullOrWhiteSpace(Album))
{
@@ -178,25 +173,25 @@ namespace MediaBrowser.Controller.Entities.Audio
songKey = albumArtist + "-" + songKey;
}
- return songKey;
+ list.Insert(0, songKey);
}
-
- var parent = AlbumEntity;
-
- if (parent != null)
+ else
{
- var parentKey = parent.GetUserDataKey();
+ var parent = AlbumEntity;
- if (IndexNumber.HasValue)
+ if (parent != null && IndexNumber.HasValue)
{
- var songKey = (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("0000 - ") : "")
- + IndexNumber.Value.ToString("0000 - ");
+ list.InsertRange(0, parent.GetUserDataKeys().Select(i =>
+ {
+ var songKey = (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("0000 - ") : "")
+ + IndexNumber.Value.ToString("0000 - ");
- return parentKey + songKey;
+ return i + songKey;
+ }));
}
}
- return base.CreateUserDataKey();
+ return list;
}
public override UnratedItem GetBlockUnratedType()
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
index e6178c183..1f3b0c92a 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicAlbum.cs
@@ -49,6 +49,15 @@ namespace MediaBrowser.Controller.Entities.Audio
}
[IgnoreDataMember]
+ public override bool SupportsCumulativeRunTimeTicks
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ [IgnoreDataMember]
public List<string> AllArtists
{
get
@@ -96,36 +105,34 @@ namespace MediaBrowser.Controller.Entities.Audio
public List<string> Artists { get; set; }
- /// <summary>
- /// Gets the user data key.
- /// </summary>
- /// <returns>System.String.</returns>
- protected override string CreateUserDataKey()
+ public override List<string> GetUserDataKeys()
{
- var id = this.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
+ var list = base.GetUserDataKeys();
- if (!string.IsNullOrWhiteSpace(id))
+ if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys)
{
- return "MusicAlbum-MusicBrainzReleaseGroup-" + id;
+ var albumArtist = AlbumArtist;
+ if (!string.IsNullOrWhiteSpace(albumArtist))
+ {
+ list.Insert(0, albumArtist + "-" + Name);
+ }
}
- id = this.GetProviderId(MetadataProviders.MusicBrainzAlbum);
+ var id = this.GetProviderId(MetadataProviders.MusicBrainzAlbum);
if (!string.IsNullOrWhiteSpace(id))
{
- return "MusicAlbum-Musicbrainz-" + id;
+ list.Insert(0, "MusicAlbum-Musicbrainz-" + id);
}
- if (ConfigurationManager.Configuration.EnableStandaloneMusicKeys)
+ id = this.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup);
+
+ if (!string.IsNullOrWhiteSpace(id))
{
- var albumArtist = AlbumArtist;
- if (!string.IsNullOrWhiteSpace(albumArtist))
- {
- return albumArtist + "-" + Name;
- }
+ list.Insert(0, "MusicAlbum-MusicBrainzReleaseGroup-" + id);
}
- return base.CreateUserDataKey();
+ return list;
}
protected override bool GetBlockUnratedValue(UserPolicy config)
@@ -172,17 +179,13 @@ namespace MediaBrowser.Controller.Entities.Audio
{
var items = GetRecursiveChildren().ToList();
- var songs = items.OfType<Audio>().ToList();
-
- var others = items.Except(songs).ToList();
-
- var totalItems = songs.Count + others.Count;
+ var totalItems = items.Count;
var numComplete = 0;
var childUpdateType = ItemUpdateType.None;
// Refresh songs
- foreach (var item in songs)
+ foreach (var item in items)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -192,7 +195,7 @@ namespace MediaBrowser.Controller.Entities.Audio
numComplete++;
double percent = numComplete;
percent /= totalItems;
- progress.Report(percent * 100);
+ progress.Report(percent * 95);
}
var parentRefreshOptions = refreshOptions;
@@ -205,19 +208,6 @@ namespace MediaBrowser.Controller.Entities.Audio
// Refresh current item
await RefreshMetadata(parentRefreshOptions, cancellationToken).ConfigureAwait(false);
- // Refresh all non-songs
- foreach (var item in others)
- {
- cancellationToken.ThrowIfCancellationRequested();
-
- var updateType = await item.RefreshMetadata(parentRefreshOptions, cancellationToken).ConfigureAwait(false);
-
- numComplete++;
- double percent = numComplete;
- percent /= totalItems;
- progress.Report(percent * 100);
- }
-
progress.Report(100);
}
}
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
index 02bcceada..6790a1bcf 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicArtist.cs
@@ -9,6 +9,7 @@ using System.Linq;
using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Common.Extensions;
namespace MediaBrowser.Controller.Entities.Audio
{
@@ -17,7 +18,12 @@ namespace MediaBrowser.Controller.Entities.Audio
/// </summary>
public class MusicArtist : Folder, IMetadataContainer, IItemByName, IHasMusicGenres, IHasDualAccess, IHasProductionLocations, IHasLookupInfo<ArtistInfo>
{
- public bool IsAccessedByName { get; set; }
+ [IgnoreDataMember]
+ public bool IsAccessedByName
+ {
+ get { return ParentId == Guid.Empty; }
+ }
+
public List<string> ProductionLocations { get; set; }
[IgnoreDataMember]
@@ -30,6 +36,15 @@ namespace MediaBrowser.Controller.Entities.Audio
}
[IgnoreDataMember]
+ public override bool SupportsCumulativeRunTimeTicks
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ [IgnoreDataMember]
public override bool SupportsAddingToPlaylist
{
get { return true; }
@@ -40,6 +55,18 @@ namespace MediaBrowser.Controller.Entities.Audio
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.ArtistNames = new[] { Name };
+ }
+
+ return LibraryManager.GetItemList(query);
+ }
+
+ [IgnoreDataMember]
protected override IEnumerable<BaseItem> ActualChildren
{
get
@@ -53,6 +80,15 @@ namespace MediaBrowser.Controller.Entities.Audio
}
}
+ public override int GetChildCount(User user)
+ {
+ if (IsAccessedByName)
+ {
+ return 0;
+ }
+ return base.GetChildCount(user);
+ }
+
public override bool IsSaveLocalMetadataEnabled()
{
if (IsAccessedByName)
@@ -80,13 +116,12 @@ namespace MediaBrowser.Controller.Entities.Audio
ProductionLocations = new List<string>();
}
- /// <summary>
- /// Gets the user data key.
- /// </summary>
- /// <returns>System.String.</returns>
- protected override string CreateUserDataKey()
+ public override List<string> GetUserDataKeys()
{
- return GetUserDataKey(this);
+ var list = base.GetUserDataKeys();
+
+ list.InsertRange(0, GetUserDataKeys(this));
+ return list;
}
/// <summary>
@@ -121,18 +156,27 @@ namespace MediaBrowser.Controller.Entities.Audio
/// </summary>
/// <param name="item">The item.</param>
/// <returns>System.String.</returns>
- private static string GetUserDataKey(MusicArtist item)
+ private static List<string> GetUserDataKeys(MusicArtist item)
{
+ var list = new List<string>();
var id = item.GetProviderId(MetadataProviders.MusicBrainzArtist);
if (!string.IsNullOrEmpty(id))
{
- return "Artist-Musicbrainz-" + id;
+ list.Add("Artist-Musicbrainz-" + id);
}
- return "Artist-" + item.Name;
+ list.Add("Artist-" + (item.Name ?? string.Empty).RemoveDiacritics());
+ return list;
}
+ public override string PresentationUniqueKey
+ {
+ get
+ {
+ return "Artist-" + (Name ?? string.Empty).RemoveDiacritics();
+ }
+ }
protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.Music);
diff --git a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
index 45304d47e..798bc79fb 100644
--- a/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
+++ b/MediaBrowser.Controller/Entities/Audio/MusicGenre.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
+using MediaBrowser.Common.Extensions;
namespace MediaBrowser.Controller.Entities.Audio
{
@@ -10,13 +11,20 @@ namespace MediaBrowser.Controller.Entities.Audio
/// </summary>
public class MusicGenre : BaseItem, IItemByName
{
- /// <summary>
- /// Gets the user data key.
- /// </summary>
- /// <returns>System.String.</returns>
- protected override string CreateUserDataKey()
+ public override List<string> GetUserDataKeys()
{
- return "MusicGenre-" + Name;
+ var list = base.GetUserDataKeys();
+
+ list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
+ return list;
+ }
+
+ public override string PresentationUniqueKey
+ {
+ get
+ {
+ return GetUserDataKeys()[0];
+ }
}
[IgnoreDataMember]
@@ -80,5 +88,13 @@ namespace MediaBrowser.Controller.Entities.Audio
return false;
}
}
+
+ public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
+ {
+ query.Genres = new[] { Name };
+ query.IncludeItemTypes = new[] { typeof(MusicVideo).Name, typeof(Audio).Name, typeof(MusicAlbum).Name, typeof(MusicArtist).Name };
+
+ return LibraryManager.GetItemList(query);
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs
index 903c5cfd5..c7a6b75ff 100644
--- a/MediaBrowser.Controller/Entities/BaseItem.cs
+++ b/MediaBrowser.Controller/Entities/BaseItem.cs
@@ -26,6 +26,7 @@ using System.Threading.Tasks;
using CommonIO;
using MediaBrowser.Controller.Sorting;
using MediaBrowser.Model.LiveTv;
+using MediaBrowser.Model.Providers;
namespace MediaBrowser.Controller.Entities
{
@@ -36,6 +37,7 @@ namespace MediaBrowser.Controller.Entities
{
protected BaseItem()
{
+ Keywords = new List<string>();
Tags = new List<string>();
Genres = new List<string>();
Studios = new List<string>();
@@ -44,6 +46,9 @@ namespace MediaBrowser.Controller.Entities
ImageInfos = new List<ItemImageInfo>();
}
+ public static readonly char[] SlugReplaceChars = { '?', '/', '&' };
+ public static char SlugChar = '-';
+
/// <summary>
/// The supported image extensions
/// </summary>
@@ -64,8 +69,22 @@ namespace MediaBrowser.Controller.Entities
[IgnoreDataMember]
public string PreferredMetadataLanguage { get; set; }
+ public long? Size { get; set; }
+ public string Container { get; set; }
+ public string ShortOverview { get; set; }
+
public List<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>
@@ -125,6 +144,29 @@ namespace MediaBrowser.Controller.Entities
}
}
+ [IgnoreDataMember]
+ public string SlugName
+ {
+ get
+ {
+ var name = Name;
+ if (string.IsNullOrWhiteSpace(name))
+ {
+ return string.Empty;
+ }
+
+ return SlugReplaceChars.Aggregate(name, (current, c) => current.Replace(c, SlugChar));
+ }
+ }
+
+ [IgnoreDataMember]
+ public bool IsUnaired
+ {
+ get { return PremiereDate.HasValue && PremiereDate.Value.ToLocalTime().Date >= DateTime.Now.Date; }
+ }
+
+ public string OriginalTitle { get; set; }
+
/// <summary>
/// Gets or sets the id.
/// </summary>
@@ -255,6 +297,11 @@ namespace MediaBrowser.Controller.Entities
if (string.IsNullOrWhiteSpace(Path))
{
+ if (SourceType == SourceType.Channel)
+ {
+ return LocationType.Remote;
+ }
+
return LocationType.Virtual;
}
@@ -301,7 +348,7 @@ namespace MediaBrowser.Controller.Entities
}
}
- private List<Tuple<StringBuilder,bool>> GetSortChunks(string s1)
+ private List<Tuple<StringBuilder, bool>> GetSortChunks(string s1)
{
var list = new List<Tuple<StringBuilder, bool>>();
@@ -407,6 +454,12 @@ namespace MediaBrowser.Controller.Entities
[IgnoreDataMember]
public DateTime DateLastRefreshed { get; set; }
+ [IgnoreDataMember]
+ public virtual bool EnableForceSaveOnDateModifiedChange
+ {
+ get { return false; }
+ }
+
/// <summary>
/// The logger
/// </summary>
@@ -494,7 +547,19 @@ namespace MediaBrowser.Controller.Entities
{
get
{
- return _sortName ?? (_sortName = CreateSortName());
+ 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
{
@@ -529,11 +594,6 @@ namespace MediaBrowser.Controller.Entities
/// <returns>System.String.</returns>
protected virtual string CreateSortName()
{
- if (!string.IsNullOrWhiteSpace(ForcedSortName))
- {
- return ModifySortChunks(ForcedSortName).ToLower();
- }
-
if (Name == null) return null; //some items may not have name filled in properly
if (!EnableAlphaNumericSorting)
@@ -588,7 +648,7 @@ namespace MediaBrowser.Controller.Entities
builder.Append(chunkBuilder);
}
//Logger.Debug("ModifySortChunks Start: {0} End: {1}", name, builder.ToString());
- return builder.ToString();
+ return builder.ToString().RemoveDiacritics();
}
[IgnoreDataMember]
@@ -653,9 +713,30 @@ namespace MediaBrowser.Controller.Entities
}
[IgnoreDataMember]
- public virtual BaseItem DisplayParent
+ public virtual Guid? DisplayParentId
+ {
+ get
+ {
+ if (ParentId == Guid.Empty)
+ {
+ return null;
+ }
+ return ParentId;
+ }
+ }
+
+ [IgnoreDataMember]
+ public BaseItem DisplayParent
{
- get { return GetParent(); }
+ get
+ {
+ var id = DisplayParentId;
+ if (!id.HasValue || id.Value == Guid.Empty)
+ {
+ return null;
+ }
+ return LibraryManager.GetItemById(id.Value);
+ }
}
/// <summary>
@@ -690,12 +771,14 @@ namespace MediaBrowser.Controller.Entities
/// Gets or sets the critic rating.
/// </summary>
/// <value>The critic rating.</value>
+ [IgnoreDataMember]
public float? CriticRating { get; set; }
/// <summary>
/// Gets or sets the critic rating summary.
/// </summary>
/// <value>The critic rating summary.</value>
+ [IgnoreDataMember]
public string CriticRatingSummary { get; set; }
/// <summary>
@@ -740,6 +823,8 @@ namespace MediaBrowser.Controller.Entities
[IgnoreDataMember]
public List<string> Tags { get; set; }
+ public List<string> Keywords { get; set; }
+
/// <summary>
/// Gets or sets the home page URL.
/// </summary>
@@ -961,9 +1046,7 @@ namespace MediaBrowser.Controller.Entities
}
: options;
- var result = await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
-
- return result;
+ return await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
}
[IgnoreDataMember]
@@ -1111,33 +1194,31 @@ namespace MediaBrowser.Controller.Entities
get { return null; }
}
- private string _userDataKey;
- /// <summary>
- /// Gets the user data key.
- /// </summary>
- /// <returns>System.String.</returns>
- public string GetUserDataKey()
+ [IgnoreDataMember]
+ public virtual string PresentationUniqueKey
{
- if (string.IsNullOrWhiteSpace(_userDataKey))
- {
- var key = CreateUserDataKey();
- _userDataKey = key;
- return key;
- }
+ get { return Id.ToString("N"); }
+ }
- return _userDataKey;
+ public virtual bool RequiresRefresh()
+ {
+ return false;
}
- protected virtual string CreateUserDataKey()
+ public virtual List<string> GetUserDataKeys()
{
+ var list = new List<string>();
+
if (SourceType == SourceType.Channel)
{
if (!string.IsNullOrWhiteSpace(ExternalId))
{
- return ExternalId;
+ list.Add(ExternalId);
}
}
- return Id.ToString();
+
+ list.Add(Id.ToString());
+ return list;
}
internal virtual bool IsValidFromResolver(BaseItem newItem)
@@ -1150,7 +1231,6 @@ namespace MediaBrowser.Controller.Entities
public void AfterMetadataRefresh()
{
_sortName = null;
- _userDataKey = null;
}
/// <summary>
@@ -1312,17 +1392,25 @@ namespace MediaBrowser.Controller.Entities
return LocalizationManager.GetRatingLevel(rating);
}
- private bool IsVisibleViaTags(User user)
+ public List<string> GetInheritedTags()
{
- var hasTags = this as IHasTags;
+ var list = new List<string>();
+ list.AddRange(Tags);
- if (hasTags != null)
+ foreach (var parent in GetParents())
{
- var policy = user.Policy;
- if (policy.BlockedTags.Any(i => hasTags.Tags.Contains(i, StringComparer.OrdinalIgnoreCase)))
- {
- return false;
- }
+ 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;
@@ -1439,7 +1527,7 @@ namespace MediaBrowser.Controller.Entities
public virtual string GetClientTypeName()
{
- if (IsFolder && SourceType == SourceType.Channel)
+ if (IsFolder && SourceType == SourceType.Channel && !(this is Channel))
{
return "ChannelFolderItem";
}
@@ -1491,11 +1579,11 @@ namespace MediaBrowser.Controller.Entities
{
if (!string.IsNullOrEmpty(info.Path))
{
- var itemByPath = LibraryManager.FindByPath(info.Path);
+ var itemByPath = LibraryManager.FindByPath(info.Path, null);
if (itemByPath == null)
{
- Logger.Warn("Unable to find linked item at path {0}", info.Path);
+ //Logger.Warn("Unable to find linked item at path {0}", info.Path);
}
return itemByPath;
@@ -1504,6 +1592,15 @@ namespace MediaBrowser.Controller.Entities
return null;
}
+ [IgnoreDataMember]
+ public virtual bool EnableRememberingTrackSelections
+ {
+ get
+ {
+ return true;
+ }
+ }
+
/// <summary>
/// Adds a studio to the item
/// </summary>
@@ -1557,13 +1654,11 @@ namespace MediaBrowser.Controller.Entities
throw new ArgumentNullException();
}
- var key = GetUserDataKey();
-
- var data = UserDataManager.GetUserData(user.Id, key);
+ var data = UserDataManager.GetUserData(user, this);
if (datePlayed.HasValue)
{
- // Incremenet
+ // Increment
data.PlayCount++;
}
@@ -1575,7 +1670,7 @@ namespace MediaBrowser.Controller.Entities
data.PlaybackPositionTicks = 0;
}
- data.LastPlayedDate = datePlayed ?? data.LastPlayedDate;
+ data.LastPlayedDate = datePlayed ?? data.LastPlayedDate ?? DateTime.UtcNow;
data.Played = true;
await UserDataManager.SaveUserData(user.Id, this, data, UserDataSaveReason.TogglePlayed, CancellationToken.None).ConfigureAwait(false);
@@ -1594,9 +1689,7 @@ namespace MediaBrowser.Controller.Entities
throw new ArgumentNullException();
}
- var key = GetUserDataKey();
-
- var data = UserDataManager.GetUserData(user.Id, key);
+ 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
@@ -1788,7 +1881,7 @@ namespace MediaBrowser.Controller.Entities
return new ItemImageInfo
{
Path = path,
- DateModified = FileSystem.GetLastWriteTimeUtc(path),
+ DateModified = chapter.ImageDateModified,
Type = imageType
};
}
@@ -1927,14 +2020,14 @@ namespace MediaBrowser.Controller.Entities
public virtual bool IsPlayed(User user)
{
- var userdata = UserDataManager.GetUserData(user.Id, GetUserDataKey());
+ var userdata = UserDataManager.GetUserData(user, this);
return userdata != null && userdata.Played;
}
public bool IsFavoriteOrLiked(User user)
{
- var userdata = UserDataManager.GetUserData(user.Id, GetUserDataKey());
+ var userdata = UserDataManager.GetUserData(user, this);
return userdata != null && (userdata.IsFavorite || (userdata.Likes ?? false));
}
@@ -1946,7 +2039,7 @@ namespace MediaBrowser.Controller.Entities
throw new ArgumentNullException("user");
}
- var userdata = UserDataManager.GetUserData(user.Id, GetUserDataKey());
+ var userdata = UserDataManager.GetUserData(user, this);
return userdata == null || !userdata.Played;
}
@@ -1977,7 +2070,6 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public virtual bool BeforeMetadataRefresh()
{
- _userDataKey = null;
_sortName = null;
var hasChanges = false;
@@ -2004,7 +2096,7 @@ namespace MediaBrowser.Controller.Entities
return path;
}
- public virtual void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user)
+ public virtual Task FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user)
{
if (RunTimeTicks.HasValue)
{
@@ -2020,6 +2112,8 @@ namespace MediaBrowser.Controller.Entities
}
}
}
+
+ return Task.FromResult(true);
}
protected Task RefreshMetadataForOwnedVideo(MetadataRefreshOptions options, string path, CancellationToken cancellationToken)
@@ -2084,7 +2178,7 @@ namespace MediaBrowser.Controller.Entities
{
get
{
- if (GetParent() is AggregateFolder || this is Channel || this is BasePluginFolder)
+ if (GetParent() is AggregateFolder || this is BasePluginFolder || this is Channel)
{
return true;
}
@@ -2094,6 +2188,10 @@ namespace MediaBrowser.Controller.Entities
{
return true;
}
+ if (view != null && string.Equals(view.ViewType, CollectionType.Channels, StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
return false;
}
@@ -2126,5 +2224,10 @@ namespace MediaBrowser.Controller.Entities
DeleteFileLocation = false
});
}
+
+ public virtual List<ExternalUrl> GetRelatedUrls()
+ {
+ return new List<ExternalUrl>();
+ }
}
} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Entities/Book.cs b/MediaBrowser.Controller/Entities/Book.cs
index 1c86a53f0..59ab95437 100644
--- a/MediaBrowser.Controller/Entities/Book.cs
+++ b/MediaBrowser.Controller/Entities/Book.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Providers;
+using System;
+using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using System.Linq;
using System.Runtime.Serialization;
@@ -6,7 +7,7 @@ using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Entities
{
- public class Book : BaseItem, IHasTags, IHasLookupInfo<BookInfo>, IHasSeries
+ public class Book : BaseItem, IHasLookupInfo<BookInfo>, IHasSeries
{
[IgnoreDataMember]
public override string MediaType
@@ -17,7 +18,32 @@ namespace MediaBrowser.Controller.Entities
}
}
+ [IgnoreDataMember]
public string SeriesName { get; set; }
+ [IgnoreDataMember]
+ public Guid? SeriesId { get; set; }
+ [IgnoreDataMember]
+ public string SeriesSortName { get; set; }
+
+ public string FindSeriesSortName()
+ {
+ return SeriesSortName;
+ }
+ public string FindSeriesName()
+ {
+ return SeriesName;
+ }
+
+ [IgnoreDataMember]
+ public override bool EnableForceSaveOnDateModifiedChange
+ {
+ get { return true; }
+ }
+
+ public Guid? FindSeriesId()
+ {
+ return SeriesId;
+ }
public override bool CanDownload()
{
diff --git a/MediaBrowser.Controller/Entities/CollectionFolder.cs b/MediaBrowser.Controller/Entities/CollectionFolder.cs
index 429700327..35dfd52e9 100644
--- a/MediaBrowser.Controller/Entities/CollectionFolder.cs
+++ b/MediaBrowser.Controller/Entities/CollectionFolder.cs
@@ -8,6 +8,7 @@ using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
+using MoreLinq;
namespace MediaBrowser.Controller.Entities
{
@@ -22,19 +23,6 @@ namespace MediaBrowser.Controller.Entities
PhysicalLocationsList = new List<string>();
}
- /// <summary>
- /// Gets a value indicating whether this instance is virtual folder.
- /// </summary>
- /// <value><c>true</c> if this instance is virtual folder; otherwise, <c>false</c>.</value>
- [IgnoreDataMember]
- public override bool IsVirtualFolder
- {
- get
- {
- return true;
- }
- }
-
[IgnoreDataMember]
protected override bool SupportsShortcutChildren
{
@@ -82,7 +70,34 @@ namespace MediaBrowser.Controller.Entities
protected override IEnumerable<FileSystemMetadata> GetFileSystemChildren(IDirectoryService directoryService)
{
- return CreateResolveArgs(directoryService).FileSystemChildren;
+ return CreateResolveArgs(directoryService, true).FileSystemChildren;
+ }
+
+ private bool _requiresRefresh;
+ public override bool RequiresRefresh()
+ {
+ var changed = base.RequiresRefresh() || _requiresRefresh;
+
+ if (!changed)
+ {
+ var locations = PhysicalLocations.ToList();
+
+ var newLocations = CreateResolveArgs(new DirectoryService(BaseItem.FileSystem), false).PhysicalLocations.ToList();
+
+ if (!locations.SequenceEqual(newLocations))
+ {
+ changed = true;
+ }
+ }
+
+ return changed;
+ }
+
+ public override bool BeforeMetadataRefresh()
+ {
+ var changed = base.BeforeMetadataRefresh() || _requiresRefresh;
+ _requiresRefresh = false;
+ return changed;
}
internal override bool IsValidFromResolver(BaseItem newItem)
@@ -97,11 +112,10 @@ namespace MediaBrowser.Controller.Entities
}
}
-
return base.IsValidFromResolver(newItem);
}
- private ItemResolveArgs CreateResolveArgs(IDirectoryService directoryService)
+ private ItemResolveArgs CreateResolveArgs(IDirectoryService directoryService, bool setPhysicalLocations)
{
var path = ContainingFolderPath;
@@ -135,7 +149,11 @@ namespace MediaBrowser.Controller.Entities
args.FileSystemDictionary = fileSystemDictionary;
}
- PhysicalLocationsList = args.PhysicalLocations.ToList();
+ _requiresRefresh = _requiresRefresh || !args.PhysicalLocations.SequenceEqual(PhysicalLocations);
+ if (setPhysicalLocations)
+ {
+ PhysicalLocationsList = args.PhysicalLocations.ToList();
+ }
return args;
}
@@ -153,15 +171,6 @@ namespace MediaBrowser.Controller.Entities
/// <returns>Task.</returns>
protected override Task ValidateChildrenInternal(IProgress<double> progress, CancellationToken cancellationToken, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService)
{
- var list = PhysicalLocationsList.ToList();
-
- CreateResolveArgs(directoryService);
-
- if (!list.SequenceEqual(PhysicalLocationsList))
- {
- return UpdateToRepository(ItemUpdateType.MetadataImport, cancellationToken);
- }
-
return Task.FromResult(true);
}
@@ -188,6 +197,7 @@ namespace MediaBrowser.Controller.Entities
/// Our children are actually just references to the ones in the physical root...
/// </summary>
/// <value>The actual children.</value>
+ [IgnoreDataMember]
protected override IEnumerable<BaseItem> ActualChildren
{
get { return GetActualChildren(); }
@@ -200,9 +210,30 @@ namespace MediaBrowser.Controller.Entities
public IEnumerable<Folder> GetPhysicalParents()
{
- return LibraryManager.RootFolder.Children
+ var rootChildren = LibraryManager.RootFolder.Children
.OfType<Folder>()
- .Where(i => i.Path != null && PhysicalLocations.Contains(i.Path, StringComparer.OrdinalIgnoreCase));
+ .ToList();
+
+ return PhysicalLocations.Where(i => !string.Equals(i, Path, StringComparison.OrdinalIgnoreCase)).SelectMany(i => GetPhysicalParents(i, rootChildren)).DistinctBy(i => i.Id);
+ }
+
+ private IEnumerable<Folder> GetPhysicalParents(string path, List<Folder> rootChildren)
+ {
+ var result = rootChildren
+ .Where(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase))
+ .ToList();
+
+ if (result.Count == 0)
+ {
+ var folder = LibraryManager.FindByPath(path, true) as Folder;
+
+ if (folder != null)
+ {
+ result.Add(folder);
+ }
+ }
+
+ return result;
}
[IgnoreDataMember]
diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs
index af1cbdf2c..0397e9a88 100644
--- a/MediaBrowser.Controller/Entities/Folder.cs
+++ b/MediaBrowser.Controller/Entities/Folder.cs
@@ -13,6 +13,7 @@ using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
+using MediaBrowser.Controller.Channels;
using MediaBrowser.Model.Channels;
namespace MediaBrowser.Controller.Entities
@@ -20,7 +21,7 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Class Folder
/// </summary>
- public class Folder : BaseItem, IHasThemeMedia, IHasTags
+ public class Folder : BaseItem, IHasThemeMedia
{
public static IUserManager UserManager { get; set; }
public static IUserViewManager UserViewManager { get; set; }
@@ -28,6 +29,9 @@ namespace MediaBrowser.Controller.Entities
public List<Guid> ThemeSongIds { get; set; }
public List<Guid> ThemeVideoIds { get; set; }
+ [IgnoreDataMember]
+ public DateTime? DateLastMediaAdded { get; set; }
+
public Folder()
{
LinkedChildren = new List<LinkedChild>();
@@ -56,6 +60,36 @@ namespace MediaBrowser.Controller.Entities
}
[IgnoreDataMember]
+ public virtual bool SupportsCumulativeRunTimeTicks
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ [IgnoreDataMember]
+ public virtual bool SupportsDateLastMediaAdded
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public override bool RequiresRefresh()
+ {
+ var baseResult = base.RequiresRefresh();
+
+ if (SupportsCumulativeRunTimeTicks && !RunTimeTicks.HasValue)
+ {
+ baseResult = true;
+ }
+
+ return baseResult;
+ }
+
+ [IgnoreDataMember]
public override string FileNameWithoutExtension
{
get
@@ -93,25 +127,12 @@ namespace MediaBrowser.Controller.Entities
/// <value><c>true</c> if this instance is root; otherwise, <c>false</c>.</value>
public bool IsRoot { get; set; }
- /// <summary>
- /// Gets a value indicating whether this instance is virtual folder.
- /// </summary>
- /// <value><c>true</c> if this instance is virtual folder; otherwise, <c>false</c>.</value>
- [IgnoreDataMember]
- public virtual bool IsVirtualFolder
- {
- get
- {
- return false;
- }
- }
-
public virtual List<LinkedChild> LinkedChildren { get; set; }
[IgnoreDataMember]
protected virtual bool SupportsShortcutChildren
{
- get { return ConfigurationManager.Configuration.EnableWindowsShortcuts; }
+ get { return false; }
}
/// <summary>
@@ -144,49 +165,15 @@ namespace MediaBrowser.Controller.Entities
item.DateModified = DateTime.UtcNow;
}
- AddChildInternal(item.Id);
-
await LibraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
}
- protected void AddChildrenInternal(List<Guid> children)
- {
- lock (_childrenSyncLock)
- {
- var newChildren = ChildIds.ToList();
- newChildren.AddRange(children);
- _children = newChildren.ToList();
- }
- }
- protected void AddChildInternal(Guid child)
- {
- lock (_childrenSyncLock)
- {
- var childIds = ChildIds.ToList();
- if (!childIds.Contains(child))
- {
- childIds.Add(child);
- _children = childIds.ToList();
- }
- }
- }
-
- protected void RemoveChildrenInternal(List<Guid> children)
- {
- lock (_childrenSyncLock)
- {
- _children = ChildIds.Except(children).ToList();
- }
- }
-
/// <summary>
/// Removes the child.
/// </summary>
/// <param name="item">The item.</param>
public void RemoveChild(BaseItem item)
{
- RemoveChildrenInternal(new[] { item.Id }.ToList());
-
item.SetParent(null);
}
@@ -199,8 +186,8 @@ namespace MediaBrowser.Controller.Entities
/// <returns>Dictionary{System.StringFunc{UserIEnumerable{BaseItem}}}.</returns>
protected virtual IEnumerable<string> GetIndexByOptions()
{
- return new List<string> {
- {"None"},
+ return new List<string> {
+ {"None"},
{"Performer"},
{"Genre"},
{"Director"},
@@ -222,41 +209,15 @@ namespace MediaBrowser.Controller.Entities
#endregion
/// <summary>
- /// The children
- /// </summary>
- private IReadOnlyList<Guid> _children;
- /// <summary>
- /// The _children sync lock
- /// </summary>
- private readonly object _childrenSyncLock = new object();
- /// <summary>
- /// Gets or sets the actual children.
- /// </summary>
- /// <value>The actual children.</value>
- protected virtual IEnumerable<Guid> ChildIds
- {
- get
- {
- lock (_childrenSyncLock)
- {
- if (_children == null)
- {
- _children = LoadChildren().ToList();
- }
- return _children.ToList();
- }
- }
- }
-
- /// <summary>
/// Gets the actual children.
/// </summary>
/// <value>The actual children.</value>
+ [IgnoreDataMember]
protected virtual IEnumerable<BaseItem> ActualChildren
{
get
{
- return ChildIds.Select(LibraryManager.GetItemById).Where(i => i != null);
+ return LoadChildren();
}
}
@@ -310,7 +271,7 @@ namespace MediaBrowser.Controller.Entities
/// Loads our children. Validation will occur externally.
/// We want this sychronous.
/// </summary>
- protected virtual IEnumerable<Guid> LoadChildren()
+ protected virtual IEnumerable<BaseItem> LoadChildren()
{
//just load our children from the repo - the library will be validated and maintained in other processes
return GetCachedChildren();
@@ -412,13 +373,6 @@ namespace MediaBrowser.Controller.Entities
if (currentChildren.TryGetValue(child.Id, out currentChild) && IsValidFromResolver(currentChild, child))
{
- var currentChildLocationType = currentChild.LocationType;
- if (currentChildLocationType != LocationType.Remote &&
- currentChildLocationType != LocationType.Virtual)
- {
- currentChild.DateModified = child.DateModified;
- }
-
await UpdateIsOffline(currentChild, false).ConfigureAwait(false);
validChildren.Add(currentChild);
@@ -440,17 +394,15 @@ namespace MediaBrowser.Controller.Entities
foreach (var item in itemsRemoved)
{
- if (item.LocationType == LocationType.Virtual ||
- item.LocationType == LocationType.Remote)
+ var itemLocationType = item.LocationType;
+ if (itemLocationType == LocationType.Virtual ||
+ itemLocationType == LocationType.Remote)
{
- // Don't remove these because there's no way to accurately validate them.
- validChildren.Add(item);
}
else if (!string.IsNullOrEmpty(item.Path) && IsPathOffline(item.Path))
{
await UpdateIsOffline(item, true).ConfigureAwait(false);
- validChildren.Add(item);
}
else
{
@@ -460,8 +412,6 @@ namespace MediaBrowser.Controller.Entities
if (actualRemovals.Count > 0)
{
- RemoveChildrenInternal(actualRemovals.Select(i => i.Id).ToList());
-
foreach (var item in actualRemovals)
{
Logger.Debug("Removed item: " + item.Path);
@@ -474,8 +424,6 @@ namespace MediaBrowser.Controller.Entities
}
await LibraryManager.CreateItems(newItems, cancellationToken).ConfigureAwait(false);
-
- AddChildrenInternal(newItems.Select(i => i.Id).ToList());
}
}
@@ -703,20 +651,41 @@ namespace MediaBrowser.Controller.Entities
/// Get our children from the repo - stubbed for now
/// </summary>
/// <returns>IEnumerable{BaseItem}.</returns>
- protected IEnumerable<Guid> GetCachedChildren()
+ protected IEnumerable<BaseItem> GetCachedChildren()
{
- return ItemRepository.GetItemIdsList(new InternalItemsQuery
+ return ItemRepository.GetItemList(new InternalItemsQuery
{
+ ParentId = Id,
+ GroupByPresentationUniqueKey = false
+ });
+ }
+
+ public virtual int GetChildCount(User user)
+ {
+ if (LinkedChildren.Count > 0)
+ {
+ if (!(this is ICollectionFolder))
+ {
+ return GetChildren(user, true).Count();
+ }
+ }
+
+ var result = GetItems(new InternalItemsQuery(user)
+ {
+ Recursive = false,
+ Limit = 0,
ParentId = Id
- });
+ }).Result;
+
+ return result.TotalRecordCount;
}
public QueryResult<BaseItem> QueryRecursive(InternalItemsQuery query)
{
var user = query.User;
- if (RequiresPostFiltering(query))
+ if (!query.ForceDirect && RequiresPostFiltering(query))
{
IEnumerable<BaseItem> items;
Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
@@ -727,7 +696,7 @@ namespace MediaBrowser.Controller.Entities
}
else
{
- items = GetRecursiveChildren(user, filter);
+ items = GetRecursiveChildren(user, query);
}
return PostFilterAndSort(items, query);
@@ -747,63 +716,23 @@ namespace MediaBrowser.Controller.Entities
{
if (!(this is ICollectionFolder))
{
- Logger.Debug("Query requires post-filtering due to LinkedChildren");
+ Logger.Debug("Query requires post-filtering due to LinkedChildren. Type: " + GetType().Name);
return true;
}
}
if (query.SortBy != null && query.SortBy.Length > 0)
{
- if (query.SortBy.Contains(ItemSortBy.DatePlayed, StringComparer.OrdinalIgnoreCase))
- {
- Logger.Debug("Query requires post-filtering due to ItemSortBy.DatePlayed");
- return true;
- }
- if (query.SortBy.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase))
- {
- Logger.Debug("Query requires post-filtering due to ItemSortBy.IsFavoriteOrLiked");
- return true;
- }
- if (query.SortBy.Contains(ItemSortBy.IsPlayed, StringComparer.OrdinalIgnoreCase))
- {
- Logger.Debug("Query requires post-filtering due to ItemSortBy.IsPlayed");
- return true;
- }
- if (query.SortBy.Contains(ItemSortBy.IsUnplayed, StringComparer.OrdinalIgnoreCase))
- {
- Logger.Debug("Query requires post-filtering due to ItemSortBy.IsUnplayed");
- return true;
- }
if (query.SortBy.Contains(ItemSortBy.AiredEpisodeOrder, StringComparer.OrdinalIgnoreCase))
{
Logger.Debug("Query requires post-filtering due to ItemSortBy.AiredEpisodeOrder");
return true;
}
- if (query.SortBy.Contains(ItemSortBy.Album, StringComparer.OrdinalIgnoreCase))
- {
- Logger.Debug("Query requires post-filtering due to ItemSortBy.Album");
- return true;
- }
- if (query.SortBy.Contains(ItemSortBy.AlbumArtist, StringComparer.OrdinalIgnoreCase))
- {
- Logger.Debug("Query requires post-filtering due to ItemSortBy.AlbumArtist");
- return true;
- }
- if (query.SortBy.Contains(ItemSortBy.Artist, StringComparer.OrdinalIgnoreCase))
- {
- Logger.Debug("Query requires post-filtering due to ItemSortBy.Artist");
- return true;
- }
if (query.SortBy.Contains(ItemSortBy.Budget, StringComparer.OrdinalIgnoreCase))
{
Logger.Debug("Query requires post-filtering due to ItemSortBy.Budget");
return true;
}
- if (query.SortBy.Contains(ItemSortBy.DateLastContentAdded, StringComparer.OrdinalIgnoreCase))
- {
- Logger.Debug("Query requires post-filtering due to ItemSortBy.DateLastContentAdded");
- return true;
- }
if (query.SortBy.Contains(ItemSortBy.GameSystem, StringComparer.OrdinalIgnoreCase))
{
Logger.Debug("Query requires post-filtering due to ItemSortBy.GameSystem");
@@ -814,16 +743,6 @@ namespace MediaBrowser.Controller.Entities
Logger.Debug("Query requires post-filtering due to ItemSortBy.Metascore");
return true;
}
- if (query.SortBy.Contains(ItemSortBy.OfficialRating, StringComparer.OrdinalIgnoreCase))
- {
- Logger.Debug("Query requires post-filtering due to ItemSortBy.OfficialRating");
- return true;
- }
- if (query.SortBy.Contains(ItemSortBy.PlayCount, StringComparer.OrdinalIgnoreCase))
- {
- Logger.Debug("Query requires post-filtering due to ItemSortBy.PlayCount");
- return true;
- }
if (query.SortBy.Contains(ItemSortBy.Players, StringComparer.OrdinalIgnoreCase))
{
Logger.Debug("Query requires post-filtering due to ItemSortBy.Players");
@@ -834,21 +753,6 @@ namespace MediaBrowser.Controller.Entities
Logger.Debug("Query requires post-filtering due to ItemSortBy.Revenue");
return true;
}
- if (query.SortBy.Contains(ItemSortBy.SeriesSortName, StringComparer.OrdinalIgnoreCase))
- {
- Logger.Debug("Query requires post-filtering due to ItemSortBy.SeriesSortName");
- return true;
- }
- if (query.SortBy.Contains(ItemSortBy.StartDate, StringComparer.OrdinalIgnoreCase))
- {
- Logger.Debug("Query requires post-filtering due to ItemSortBy.StartDate");
- return true;
- }
- if (query.SortBy.Contains(ItemSortBy.Studio, StringComparer.OrdinalIgnoreCase))
- {
- Logger.Debug("Query requires post-filtering due to ItemSortBy.Studio");
- return true;
- }
if (query.SortBy.Contains(ItemSortBy.VideoBitRate, StringComparer.OrdinalIgnoreCase))
{
Logger.Debug("Query requires post-filtering due to ItemSortBy.VideoBitRate");
@@ -862,42 +766,6 @@ namespace MediaBrowser.Controller.Entities
return true;
}
- if (query.PersonIds.Length > 0)
- {
- Logger.Debug("Query requires post-filtering due to PersonIds");
- return true;
- }
-
- if (query.IsLiked.HasValue)
- {
- Logger.Debug("Query requires post-filtering due to IsLiked");
- return true;
- }
-
- if (query.IsFavoriteOrLiked.HasValue)
- {
- Logger.Debug("Query requires post-filtering due to IsFavoriteOrLiked");
- return true;
- }
-
- if (query.IsFavorite.HasValue)
- {
- Logger.Debug("Query requires post-filtering due to IsFavorite");
- return true;
- }
-
- if (query.IsResumable.HasValue)
- {
- Logger.Debug("Query requires post-filtering due to IsResumable");
- return true;
- }
-
- if (query.IsPlayed.HasValue)
- {
- Logger.Debug("Query requires post-filtering due to IsPlayed");
- return true;
- }
-
if (query.IsInBoxSet.HasValue)
{
Logger.Debug("Query requires post-filtering due to IsInBoxSet");
@@ -911,30 +779,6 @@ namespace MediaBrowser.Controller.Entities
return true;
}
- if (query.HasImdbId.HasValue)
- {
- Logger.Debug("Query requires post-filtering due to HasImdbId");
- return true;
- }
-
- if (query.HasTmdbId.HasValue)
- {
- Logger.Debug("Query requires post-filtering due to HasTmdbId");
- return true;
- }
-
- if (query.HasTvdbId.HasValue)
- {
- Logger.Debug("Query requires post-filtering due to HasTvdbId");
- return true;
- }
-
- if (query.IsYearMismatched.HasValue)
- {
- Logger.Debug("Query requires post-filtering due to IsYearMismatched");
- return true;
- }
-
if (query.HasOfficialRating.HasValue)
{
Logger.Debug("Query requires post-filtering due to HasOfficialRating");
@@ -984,26 +828,6 @@ namespace MediaBrowser.Controller.Entities
return true;
}
- if (query.ImageTypes.Length > 0)
- {
- Logger.Debug("Query requires post-filtering due to ImageTypes");
- return true;
- }
-
- // Apply studio filter
- if (query.StudioIds.Length > 0)
- {
- Logger.Debug("Query requires post-filtering due to StudioIds");
- return true;
- }
-
- // Apply genre filter
- if (query.GenreIds.Length > 0)
- {
- Logger.Debug("Query requires post-filtering due to GenreIds");
- return true;
- }
-
// Apply person filter
if (query.ItemIdsFromPersonFilters != null)
{
@@ -1023,31 +847,7 @@ namespace MediaBrowser.Controller.Entities
return true;
}
- if (query.OfficialRatings.Length > 0)
- {
- Logger.Debug("Query requires post-filtering due to OfficialRatings");
- return true;
- }
-
- if (query.IsMissing.HasValue)
- {
- Logger.Debug("Query requires post-filtering due to IsMissing");
- return true;
- }
-
- if (query.IsUnaired.HasValue)
- {
- Logger.Debug("Query requires post-filtering due to IsUnaired");
- return true;
- }
-
- if (query.IsVirtualUnaired.HasValue)
- {
- Logger.Debug("Query requires post-filtering due to IsVirtualUnaired");
- return true;
- }
-
- if (UserViewBuilder.CollapseBoxSetItems(query, this, query.User))
+ if (UserViewBuilder.CollapseBoxSetItems(query, this, query.User, ConfigurationManager))
{
Logger.Debug("Query requires post-filtering due to CollapseBoxSetItems");
return true;
@@ -1059,30 +859,6 @@ namespace MediaBrowser.Controller.Entities
return true;
}
- if (!string.IsNullOrWhiteSpace(query.NameContains))
- {
- Logger.Debug("Query requires post-filtering due to NameContains");
- return true;
- }
-
- if (!string.IsNullOrWhiteSpace(query.NameLessThan))
- {
- Logger.Debug("Query requires post-filtering due to NameLessThan");
- return true;
- }
-
- if (!string.IsNullOrWhiteSpace(query.NameStartsWith))
- {
- Logger.Debug("Query requires post-filtering due to NameStartsWith");
- return true;
- }
-
- if (!string.IsNullOrWhiteSpace(query.NameStartsWithOrGreater))
- {
- Logger.Debug("Query requires post-filtering due to NameStartsWithOrGreater");
- return true;
- }
-
if (query.AirDays.Length > 0)
{
Logger.Debug("Query requires post-filtering due to AirDays");
@@ -1107,22 +883,21 @@ namespace MediaBrowser.Controller.Entities
return true;
}
- if (query.AlbumNames.Length > 0)
- {
- Logger.Debug("Query requires post-filtering due to AlbumNames");
- return true;
- }
+ return false;
+ }
- if (query.ArtistNames.Length > 0)
+ public Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
+ {
+ if (query.ItemIds.Length > 0)
{
- Logger.Debug("Query requires post-filtering due to ArtistNames");
- return true;
+ var specificItems = query.ItemIds.Select(LibraryManager.GetItemById).Where(i => i != null).ToList();
+ return Task.FromResult(PostFilterAndSort(specificItems, query));
}
- return false;
+ return GetItemsInternal(query);
}
- public virtual async Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
+ protected virtual async Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query)
{
if (SourceType == SourceType.Channel)
{
@@ -1171,18 +946,16 @@ namespace MediaBrowser.Controller.Entities
else
{
items = query.Recursive
- ? GetRecursiveChildren(user, filter)
+ ? GetRecursiveChildren(user, query)
: GetChildren(user, true).Where(filter);
}
- var result = PostFilterAndSort(items, query);
-
- return result;
+ return PostFilterAndSort(items, query);
}
protected QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, InternalItemsQuery query)
{
- return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager);
+ return UserViewBuilder.PostFilterAndSort(items, this, null, query, LibraryManager, ConfigurationManager);
}
public virtual IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
@@ -1210,19 +983,14 @@ namespace MediaBrowser.Controller.Entities
/// <summary>
/// Adds the children to list.
/// </summary>
- /// <param name="user">The user.</param>
- /// <param name="includeLinkedChildren">if set to <c>true</c> [include linked children].</param>
- /// <param name="result">The result.</param>
- /// <param name="recursive">if set to <c>true</c> [recursive].</param>
- /// <param name="filter">The filter.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
- private void AddChildren(User user, bool includeLinkedChildren, Dictionary<Guid, BaseItem> result, bool recursive, Func<BaseItem, bool> filter)
+ 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 (filter == null || filter(child))
+ if (query == null || UserViewBuilder.FilterItem(child, query))
{
result[child.Id] = child;
}
@@ -1231,7 +999,7 @@ namespace MediaBrowser.Controller.Entities
{
var folder = (Folder)child;
- folder.AddChildren(user, includeLinkedChildren, result, true, filter);
+ folder.AddChildren(user, includeLinkedChildren, result, true, query);
}
}
}
@@ -1242,7 +1010,7 @@ namespace MediaBrowser.Controller.Entities
{
if (child.IsVisible(user))
{
- if (filter == null || filter(child))
+ if (query == null || UserViewBuilder.FilterItem(child, query))
{
result[child.Id] = child;
}
@@ -1260,10 +1028,10 @@ namespace MediaBrowser.Controller.Entities
/// <exception cref="System.ArgumentNullException"></exception>
public IEnumerable<BaseItem> GetRecursiveChildren(User user, bool includeLinkedChildren = true)
{
- return GetRecursiveChildren(user, i => true);
+ return GetRecursiveChildren(user, null);
}
- public virtual IEnumerable<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter)
+ public virtual IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query)
{
if (user == null)
{
@@ -1272,7 +1040,7 @@ namespace MediaBrowser.Controller.Entities
var result = new Dictionary<Guid, BaseItem>();
- AddChildren(user, true, result, true, filter);
+ AddChildren(user, true, result, true, query);
return result.Values;
}
@@ -1288,33 +1056,42 @@ namespace MediaBrowser.Controller.Entities
public IList<BaseItem> GetRecursiveChildren(Func<BaseItem, bool> filter)
{
- var list = new List<BaseItem>();
+ var result = new Dictionary<Guid, BaseItem>();
- AddChildrenToList(list, true, filter);
+ AddChildrenToList(result, true, true, filter);
- return list;
+ return result.Values.ToList();
}
/// <summary>
/// Adds the children to list.
/// </summary>
- /// <param name="list">The list.</param>
- /// <param name="recursive">if set to <c>true</c> [recursive].</param>
- /// <param name="filter">The filter.</param>
- private void AddChildrenToList(List<BaseItem> list, bool recursive, Func<BaseItem, bool> filter)
+ 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))
{
- list.Add(child);
+ result[child.Id] = child;
}
if (recursive && child.IsFolder)
{
var folder = (Folder)child;
- folder.AddChildrenToList(list, true, filter);
+ // We can only support includeLinkedChildren for the first folder, or we might end up stuck in a loop of linked items
+ folder.AddChildrenToList(result, false, true, filter);
+ }
+ }
+
+ if (includeLinkedChildren)
+ {
+ foreach (var child in GetLinkedChildren())
+ {
+ if (filter == null || filter(child))
+ {
+ result[child.Id] = child;
+ }
}
}
}
@@ -1520,13 +1297,12 @@ namespace MediaBrowser.Controller.Entities
User = user,
Recursive = true,
IsFolder = false,
- IsUnaired = false
-
+ EnableTotalRecordCount = false
};
- if (!user.Configuration.DisplayMissingEpisodes)
+ if (!user.Configuration.DisplayMissingEpisodes || !user.Configuration.DisplayUnairedEpisodes)
{
- query.IsMissing = false;
+ query.ExcludeLocationTypes = new[] { LocationType.Virtual };
}
var itemsResult = await GetItems(query).ConfigureAwait(false);
@@ -1548,7 +1324,8 @@ namespace MediaBrowser.Controller.Entities
{
User = user,
Recursive = true,
- IsFolder = false
+ IsFolder = false,
+ EnableTotalRecordCount = false
}).ConfigureAwait(false);
@@ -1558,38 +1335,18 @@ namespace MediaBrowser.Controller.Entities
await Task.WhenAll(tasks).ConfigureAwait(false);
}
- /// <summary>
- /// Finds an item by path, recursively
- /// </summary>
- /// <param name="path">The path.</param>
- /// <returns>BaseItem.</returns>
- /// <exception cref="System.ArgumentNullException"></exception>
- public BaseItem FindByPath(string path)
+ public override bool IsPlayed(User user)
{
- if (string.IsNullOrEmpty(path))
- {
- throw new ArgumentNullException();
- }
-
- if (string.Equals(Path, path, StringComparison.OrdinalIgnoreCase))
- {
- return this;
- }
-
- if (PhysicalLocations.Contains(path, StringComparer.OrdinalIgnoreCase))
+ var itemsResult = GetItems(new InternalItemsQuery(user)
{
- return this;
- }
+ Recursive = true,
+ IsFolder = false,
+ ExcludeLocationTypes = new[] { LocationType.Virtual },
+ EnableTotalRecordCount = false
- return GetRecursiveChildren(i => string.Equals(i.Path, path, StringComparison.OrdinalIgnoreCase) ||
- (!i.IsFolder && !i.IsInMixedFolder && string.Equals(i.ContainingFolderPath, path, StringComparison.OrdinalIgnoreCase)) ||
- i.PhysicalLocations.Contains(path, StringComparer.OrdinalIgnoreCase))
- .FirstOrDefault();
- }
+ }).Result;
- public override bool IsPlayed(User user)
- {
- return GetRecursiveChildren(user, i => !i.IsFolder && i.LocationType != LocationType.Virtual)
+ return itemsResult.Items
.All(i => i.IsPlayed(user));
}
@@ -1598,65 +1355,79 @@ namespace MediaBrowser.Controller.Entities
return !IsPlayed(user);
}
- public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user)
+ [IgnoreDataMember]
+ public virtual bool SupportsUserDataFromChildren
{
- var recursiveItemCount = 0;
- var unplayed = 0;
-
- double totalPercentPlayed = 0;
-
- IEnumerable<BaseItem> children;
- var folder = this;
-
- var season = folder as Season;
-
- if (season != null)
+ get
{
- children = season.GetEpisodes(user).Where(i => i.LocationType != LocationType.Virtual);
+ // 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;
+ }
+
+ return true;
}
- else
+ }
+
+ public override async Task FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user)
+ {
+ if (!SupportsUserDataFromChildren)
{
- children = folder.GetRecursiveChildren(user, i => !i.IsFolder && i.LocationType != LocationType.Virtual);
+ return;
}
- // Loop through each recursive child
- foreach (var child in children)
+ var unplayedQueryResult = await GetItems(new InternalItemsQuery(user)
{
- recursiveItemCount++;
-
- var isUnplayed = true;
+ Recursive = true,
+ IsFolder = false,
+ IsVirtualItem = false,
+ EnableTotalRecordCount = true,
+ Limit = 0,
+ IsPlayed = false
- var itemUserData = UserDataManager.GetUserData(user.Id, child.GetUserDataKey());
+ }).ConfigureAwait(false);
- // Incrememt totalPercentPlayed
- if (itemUserData != null)
- {
- if (itemUserData.Played)
- {
- totalPercentPlayed += 100;
+ var allItemsQueryResult = await GetItems(new InternalItemsQuery(user)
+ {
+ Recursive = true,
+ IsFolder = false,
+ IsVirtualItem = false,
+ EnableTotalRecordCount = true,
+ Limit = 0
- isUnplayed = false;
- }
- else if (itemUserData.PlaybackPositionTicks > 0 && child.RunTimeTicks.HasValue && child.RunTimeTicks.Value > 0)
- {
- double itemPercent = itemUserData.PlaybackPositionTicks;
- itemPercent /= child.RunTimeTicks.Value;
- totalPercentPlayed += itemPercent;
- }
- }
+ }).ConfigureAwait(false);
- if (isUnplayed)
- {
- unplayed++;
- }
+ if (itemDto != null)
+ {
+ itemDto.RecursiveItemCount = allItemsQueryResult.TotalRecordCount;
}
- dto.UnplayedItemCount = unplayed;
+ double recursiveItemCount = allItemsQueryResult.TotalRecordCount;
+ double unplayedCount = unplayedQueryResult.TotalRecordCount;
if (recursiveItemCount > 0)
{
- dto.PlayedPercentage = totalPercentPlayed / recursiveItemCount;
+ var unplayedPercentage = (unplayedCount / recursiveItemCount) * 100;
+ dto.PlayedPercentage = 100 - unplayedPercentage;
dto.Played = dto.PlayedPercentage.Value >= 100;
+ dto.UnplayedItemCount = unplayedQueryResult.TotalRecordCount;
}
}
}
diff --git a/MediaBrowser.Controller/Entities/Game.cs b/MediaBrowser.Controller/Entities/Game.cs
index e597b2a15..54386a179 100644
--- a/MediaBrowser.Controller/Entities/Game.cs
+++ b/MediaBrowser.Controller/Entities/Game.cs
@@ -4,10 +4,11 @@ using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Runtime.Serialization;
namespace MediaBrowser.Controller.Entities
{
- public class Game : BaseItem, IHasTrailers, IHasThemeMedia, IHasTags, IHasScreenshots, ISupportsPlaceHolders, IHasLookupInfo<GameInfo>
+ public class Game : BaseItem, IHasTrailers, IHasThemeMedia, IHasScreenshots, ISupportsPlaceHolders, IHasLookupInfo<GameInfo>
{
public List<Guid> ThemeSongIds { get; set; }
public List<Guid> ThemeVideoIds { get; set; }
@@ -32,6 +33,12 @@ namespace MediaBrowser.Controller.Entities
locationType != LocationType.Virtual;
}
+ [IgnoreDataMember]
+ public override bool EnableForceSaveOnDateModifiedChange
+ {
+ get { return true; }
+ }
+
/// <summary>
/// Gets or sets the remote trailers.
/// </summary>
@@ -42,6 +49,7 @@ namespace MediaBrowser.Controller.Entities
/// 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; }
@@ -76,15 +84,16 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public List<string> MultiPartGameFiles { get; set; }
- protected override string CreateUserDataKey()
+ public override List<string> GetUserDataKeys()
{
+ var list = base.GetUserDataKeys();
var id = this.GetProviderId(MetadataProviders.Gamesdb);
if (!string.IsNullOrEmpty(id))
{
- return "Game-Gamesdb-" + id;
+ list.Insert(0, "Game-Gamesdb-" + id);
}
- return base.CreateUserDataKey();
+ return list;
}
public override IEnumerable<string> GetDeletePaths()
diff --git a/MediaBrowser.Controller/Entities/GameGenre.cs b/MediaBrowser.Controller/Entities/GameGenre.cs
index d2b6b4856..45e766c0f 100644
--- a/MediaBrowser.Controller/Entities/GameGenre.cs
+++ b/MediaBrowser.Controller/Entities/GameGenre.cs
@@ -2,18 +2,26 @@
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
+using MediaBrowser.Common.Extensions;
namespace MediaBrowser.Controller.Entities
{
public class GameGenre : BaseItem, IItemByName
{
- /// <summary>
- /// Gets the user data key.
- /// </summary>
- /// <returns>System.String.</returns>
- protected override string CreateUserDataKey()
+ public override List<string> GetUserDataKeys()
{
- return "GameGenre-" + Name;
+ var list = base.GetUserDataKeys();
+
+ list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
+ return list;
+ }
+
+ public override string PresentationUniqueKey
+ {
+ get
+ {
+ return GetUserDataKeys()[0];
+ }
}
/// <summary>
@@ -63,6 +71,14 @@ namespace MediaBrowser.Controller.Entities
return i => i is Game && i.Genres.Contains(Name, StringComparer.OrdinalIgnoreCase);
}
+ public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
+ {
+ query.Genres = new[] { Name };
+ query.IncludeItemTypes = new[] { typeof(Game).Name };
+
+ return LibraryManager.GetItemList(query);
+ }
+
[IgnoreDataMember]
public override bool SupportsPeople
{
diff --git a/MediaBrowser.Controller/Entities/GameSystem.cs b/MediaBrowser.Controller/Entities/GameSystem.cs
index bc35c4738..1c09ee507 100644
--- a/MediaBrowser.Controller/Entities/GameSystem.cs
+++ b/MediaBrowser.Controller/Entities/GameSystem.cs
@@ -2,6 +2,7 @@
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using System;
+using System.Collections.Generic;
using MediaBrowser.Model.Users;
namespace MediaBrowser.Controller.Entities
@@ -31,17 +32,15 @@ namespace MediaBrowser.Controller.Entities
/// <value>The game system.</value>
public string GameSystemName { get; set; }
- /// <summary>
- /// Gets the user data key.
- /// </summary>
- /// <returns>System.String.</returns>
- protected override string CreateUserDataKey()
+ public override List<string> GetUserDataKeys()
{
+ var list = base.GetUserDataKeys();
+
if (!string.IsNullOrEmpty(GameSystemName))
{
- return "GameSystem-" + GameSystemName;
+ list.Insert(0, "GameSystem-" + GameSystemName);
}
- return base.CreateUserDataKey();
+ return list;
}
protected override bool GetBlockUnratedValue(UserPolicy config)
diff --git a/MediaBrowser.Controller/Entities/Genre.cs b/MediaBrowser.Controller/Entities/Genre.cs
index 233e1e0fd..cc5aebb2a 100644
--- a/MediaBrowser.Controller/Entities/Genre.cs
+++ b/MediaBrowser.Controller/Entities/Genre.cs
@@ -3,6 +3,7 @@ using MediaBrowser.Controller.Entities.Audio;
using System;
using System.Collections.Generic;
using System.Linq;
+using MediaBrowser.Common.Extensions;
namespace MediaBrowser.Controller.Entities
{
@@ -11,13 +12,20 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class Genre : BaseItem, IItemByName
{
- /// <summary>
- /// Gets the user data key.
- /// </summary>
- /// <returns>System.String.</returns>
- protected override string CreateUserDataKey()
+ public override List<string> GetUserDataKeys()
{
- return "Genre-" + Name;
+ var list = base.GetUserDataKeys();
+
+ list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
+ return list;
+ }
+
+ public override string PresentationUniqueKey
+ {
+ get
+ {
+ return GetUserDataKeys()[0];
+ }
}
/// <summary>
@@ -67,6 +75,14 @@ namespace MediaBrowser.Controller.Entities
return i => !(i is Game) && !(i is IHasMusicGenres) && i.Genres.Contains(Name, StringComparer.OrdinalIgnoreCase);
}
+ public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
+ {
+ query.Genres = new[] { Name };
+ 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
{
diff --git a/MediaBrowser.Controller/Entities/IHasImages.cs b/MediaBrowser.Controller/Entities/IHasImages.cs
index a38b7394d..226748098 100644
--- a/MediaBrowser.Controller/Entities/IHasImages.cs
+++ b/MediaBrowser.Controller/Entities/IHasImages.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Providers;
+using System;
+using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using System.Collections.Generic;
using System.Threading;
diff --git a/MediaBrowser.Controller/Entities/IHasMetadata.cs b/MediaBrowser.Controller/Entities/IHasMetadata.cs
index 0e4ae04ff..378c4a390 100644
--- a/MediaBrowser.Controller/Entities/IHasMetadata.cs
+++ b/MediaBrowser.Controller/Entities/IHasMetadata.cs
@@ -17,7 +17,7 @@ namespace MediaBrowser.Controller.Entities
/// Gets the date modified.
/// </summary>
/// <value>The date modified.</value>
- DateTime DateModified { get; }
+ DateTime DateModified { get; set; }
/// <summary>
/// Gets or sets the date last saved.
@@ -25,6 +25,8 @@ namespace MediaBrowser.Controller.Entities
/// <value>The date last saved.</value>
DateTime DateLastSaved { get; set; }
+ SourceType SourceType { get; set; }
+
/// <summary>
/// Gets or sets the date last refreshed.
/// </summary>
@@ -47,5 +49,9 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
/// <value><c>true</c> if [supports people]; otherwise, <c>false</c>.</value>
bool SupportsPeople { get; }
+
+ bool RequiresRefresh();
+
+ bool EnableForceSaveOnDateModifiedChange { get; }
}
}
diff --git a/MediaBrowser.Controller/Entities/IHasSeries.cs b/MediaBrowser.Controller/Entities/IHasSeries.cs
index 64c33a376..531f58788 100644
--- a/MediaBrowser.Controller/Entities/IHasSeries.cs
+++ b/MediaBrowser.Controller/Entities/IHasSeries.cs
@@ -1,4 +1,6 @@

+using System;
+
namespace MediaBrowser.Controller.Entities
{
public interface IHasSeries
@@ -7,6 +9,11 @@ namespace MediaBrowser.Controller.Entities
/// Gets the name of the series.
/// </summary>
/// <value>The name of the series.</value>
- string SeriesName { get; }
+ string SeriesName { get; set; }
+ string FindSeriesName();
+ string SeriesSortName { get; set; }
+ string FindSeriesSortName();
+ Guid? SeriesId { get; set; }
+ Guid? FindSeriesId();
}
}
diff --git a/MediaBrowser.Controller/Entities/IHasTrailers.cs b/MediaBrowser.Controller/Entities/IHasTrailers.cs
index bc1c7d875..e5cbdff72 100644
--- a/MediaBrowser.Controller/Entities/IHasTrailers.cs
+++ b/MediaBrowser.Controller/Entities/IHasTrailers.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
+using System.Linq;
namespace MediaBrowser.Controller.Entities
{
@@ -18,11 +19,20 @@ namespace MediaBrowser.Controller.Entities
/// <value>The local trailer ids.</value>
List<Guid> LocalTrailerIds { get; set; }
List<Guid> RemoteTrailerIds { get; set; }
+ }
+ public static class HasTrailerExtensions
+ {
/// <summary>
/// Gets the trailer ids.
/// </summary>
/// <returns>List&lt;Guid&gt;.</returns>
- List<Guid> GetTrailerIds();
+ 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
index 34a820853..2495b0ccd 100644
--- a/MediaBrowser.Controller/Entities/IHasUserData.cs
+++ b/MediaBrowser.Controller/Entities/IHasUserData.cs
@@ -1,4 +1,6 @@
-using MediaBrowser.Model.Dto;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using MediaBrowser.Model.Dto;
namespace MediaBrowser.Controller.Entities
{
@@ -7,11 +9,7 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public interface IHasUserData : IHasId
{
- /// <summary>
- /// Gets the user data key.
- /// </summary>
- /// <returns>System.String.</returns>
- string GetUserDataKey();
+ List<string> GetUserDataKeys();
/// <summary>
/// Fills the user data dto values.
@@ -19,6 +17,8 @@ namespace MediaBrowser.Controller.Entities
/// <param name="dto">The dto.</param>
/// <param name="userData">The user data.</param>
/// <param name="user">The user.</param>
- void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user);
+ Task FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, BaseItemDto itemDto, User user);
+
+ bool EnableRememberingTrackSelections { get; }
}
}
diff --git a/MediaBrowser.Controller/Entities/IItemByName.cs b/MediaBrowser.Controller/Entities/IItemByName.cs
index e6667290c..2ac4af1af 100644
--- a/MediaBrowser.Controller/Entities/IItemByName.cs
+++ b/MediaBrowser.Controller/Entities/IItemByName.cs
@@ -15,11 +15,7 @@ namespace MediaBrowser.Controller.Entities
/// <returns>IEnumerable{BaseItem}.</returns>
IEnumerable<BaseItem> GetTaggedItems(IEnumerable<BaseItem> inputItems);
- /// <summary>
- /// Gets the item filter.
- /// </summary>
- /// <returns>Func&lt;BaseItem, System.Boolean&gt;.</returns>
- Func<BaseItem, bool> GetItemFilter();
+ IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query);
}
public interface IHasDualAccess : IItemByName
diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
index b568aec18..69cab5ec5 100644
--- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
+++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
@@ -19,7 +19,7 @@ namespace MediaBrowser.Controller.Entities
public User User { get; set; }
- public Func<BaseItem, bool> Filter { get; set; }
+ public BaseItem SimilarTo { get; set; }
public bool? IsFolder { get; set; }
public bool? IsFavorite { get; set; }
@@ -33,7 +33,9 @@ namespace MediaBrowser.Controller.Entities
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 string[] Keywords { get; set; }
public bool? IsMissing { get; set; }
public bool? IsUnaired { get; set; }
@@ -44,12 +46,17 @@ namespace MediaBrowser.Controller.Entities
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 Name { get; set; }
+ public string SlugName { 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; }
@@ -58,7 +65,6 @@ namespace MediaBrowser.Controller.Entities
public bool? IsInBoxSet { get; set; }
public bool? IsLocked { get; set; }
public bool? IsPlaceHolder { get; set; }
- public bool? IsYearMismatched { get; set; }
public bool? HasImdbId { get; set; }
public bool? HasOverview { get; set; }
@@ -105,12 +111,15 @@ namespace MediaBrowser.Controller.Entities
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? IsCurrentSchema { get; set; }
public bool? HasDeadParentId { get; set; }
public bool? IsOffline { get; set; }
+ public bool? IsVirtualItem { get; set; }
public Guid? ParentId { get; set; }
public string[] AncestorIds { get; set; }
@@ -122,7 +131,6 @@ namespace MediaBrowser.Controller.Entities
public SourceType[] SourceTypes { get; set; }
public SourceType[] ExcludeSourceTypes { get; set; }
public TrailerType[] TrailerTypes { get; set; }
- public TrailerType[] ExcludeTrailerTypes { get; set; }
public DayOfWeek[] AirDays { get; set; }
public SeriesStatus[] SeriesStatuses { get; set; }
@@ -130,17 +138,31 @@ namespace MediaBrowser.Controller.Entities
public string[] AlbumNames { get; set; }
public string[] ArtistNames { get; set; }
-
+ public string[] ExcludeArtistIds { get; set; }
+ public string AncestorWithPresentationUniqueKey { get; set; }
+
+ public bool GroupByPresentationUniqueKey { 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 InternalItemsQuery()
{
+ GroupByPresentationUniqueKey = true;
+ EnableTotalRecordCount = true;
+
AlbumNames = new string[] { };
ArtistNames = new string[] { };
-
+ ExcludeArtistIds = new string[] { };
+ ExcludeProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+
BlockUnratedItems = new UnratedItem[] { };
Tags = new string[] { };
OfficialRatings = new string[] { };
SortBy = new string[] { };
MediaTypes = new string[] { };
+ Keywords = new string[] { };
IncludeItemTypes = new string[] { };
ExcludeItemTypes = new string[] { };
Genres = new string[] { };
@@ -154,16 +176,17 @@ namespace MediaBrowser.Controller.Entities
PersonIds = new string[] { };
ChannelIds = new string[] { };
ItemIds = new string[] { };
+ ExcludeItemIds = new string[] { };
AncestorIds = new string[] { };
TopParentIds = new string[] { };
ExcludeTags = new string[] { };
+ ExcludeInheritedTags = new string[] { };
LocationTypes = new LocationType[] { };
ExcludeLocationTypes = new LocationType[] { };
PresetViews = new string[] { };
SourceTypes = new SourceType[] { };
ExcludeSourceTypes = new SourceType[] { };
TrailerTypes = new TrailerType[] { };
- ExcludeTrailerTypes = new TrailerType[] { };
AirDays = new DayOfWeek[] { };
SeriesStatuses = new SeriesStatus[] { };
}
@@ -171,6 +194,11 @@ namespace MediaBrowser.Controller.Entities
public InternalItemsQuery(User user)
: this()
{
+ SetUser(user);
+ }
+
+ public void SetUser(User user)
+ {
if (user != null)
{
var policy = user.Policy;
@@ -181,7 +209,7 @@ namespace MediaBrowser.Controller.Entities
BlockUnratedItems = policy.BlockUnratedItems;
}
- ExcludeTags = policy.BlockedTags;
+ ExcludeInheritedTags = policy.BlockedTags;
User = user;
}
diff --git a/MediaBrowser.Controller/Entities/IHasKeywords.cs b/MediaBrowser.Controller/Entities/KeywordExtensions.cs
index ab9eb4aee..5c9afdf3d 100644
--- a/MediaBrowser.Controller/Entities/IHasKeywords.cs
+++ b/MediaBrowser.Controller/Entities/KeywordExtensions.cs
@@ -1,21 +1,11 @@
using System;
-using System.Collections.Generic;
using System.Linq;
namespace MediaBrowser.Controller.Entities
{
- public interface IHasKeywords
- {
- /// <summary>
- /// Gets or sets the keywords.
- /// </summary>
- /// <value>The keywords.</value>
- List<string> Keywords { get; set; }
- }
-
public static class KeywordExtensions
{
- public static void AddKeyword(this IHasKeywords item, string name)
+ public static void AddKeyword(this BaseItem item, string name)
{
if (string.IsNullOrWhiteSpace(name))
{
diff --git a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
index cd3e07ea3..4effc162e 100644
--- a/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
+++ b/MediaBrowser.Controller/Entities/Movies/BoxSet.cs
@@ -8,13 +8,14 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
+using MediaBrowser.Controller.Entities.Audio;
namespace MediaBrowser.Controller.Entities.Movies
{
/// <summary>
/// Class BoxSet
/// </summary>
- public class BoxSet : Folder, IHasTrailers, IHasKeywords, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IHasShares
+ public class BoxSet : Folder, IHasTrailers, IHasDisplayOrder, IHasLookupInfo<BoxSetInfo>, IHasShares
{
public List<Share> Shares { get; set; }
@@ -25,7 +26,6 @@ namespace MediaBrowser.Controller.Entities.Movies
RemoteTrailerIds = new List<Guid>();
DisplayOrder = ItemSortBy.PremiereDate;
- Keywords = new List<string>();
Shares = new List<Share>();
}
@@ -47,12 +47,6 @@ namespace MediaBrowser.Controller.Entities.Movies
public List<MediaUrl> RemoteTrailers { get; set; }
/// <summary>
- /// Gets or sets the tags.
- /// </summary>
- /// <value>The tags.</value>
- public List<string> Keywords { get; set; }
-
- /// <summary>
/// Gets or sets the display order.
/// </summary>
/// <value>The display order.</value>
@@ -118,7 +112,7 @@ namespace MediaBrowser.Controller.Entities.Movies
// Gather all possible ratings
var ratings = GetRecursiveChildren()
.Concat(GetLinkedChildren())
- .Where(i => i is Movie || i is Series)
+ .Where(i => i is Movie || i is Series || i is MusicAlbum || i is Game)
.Select(i => i.OfficialRating)
.Where(i => !string.IsNullOrEmpty(i))
.Distinct(StringComparer.OrdinalIgnoreCase)
diff --git a/MediaBrowser.Controller/Entities/Movies/Movie.cs b/MediaBrowser.Controller/Entities/Movies/Movie.cs
index f5c2a9935..c7a833c58 100644
--- a/MediaBrowser.Controller/Entities/Movies/Movie.cs
+++ b/MediaBrowser.Controller/Entities/Movies/Movie.cs
@@ -8,18 +8,17 @@ using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
+using MediaBrowser.Model.Providers;
namespace MediaBrowser.Controller.Entities.Movies
{
/// <summary>
/// Class Movie
/// </summary>
- public class Movie : Video, IHasCriticRating, IHasSpecialFeatures, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasAwards, IHasMetascore, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping, IHasOriginalTitle
+ public class Movie : Video, IHasCriticRating, IHasSpecialFeatures, IHasProductionLocations, IHasBudget, IHasTrailers, IHasThemeMedia, IHasTaglines, IHasAwards, IHasMetascore, IHasLookupInfo<MovieInfo>, ISupportsBoxSetGrouping, IHasOriginalTitle
{
public List<Guid> SpecialFeatureIds { get; set; }
- public string OriginalTitle { get; set; }
-
public List<Guid> ThemeSongIds { get; set; }
public List<Guid> ThemeVideoIds { get; set; }
public List<string> ProductionLocations { get; set; }
@@ -33,7 +32,6 @@ namespace MediaBrowser.Controller.Entities.Movies
ThemeSongIds = new List<Guid>();
ThemeVideoIds = new List<Guid>();
Taglines = new List<string>();
- Keywords = new List<string>();
ProductionLocations = new List<string>();
}
@@ -43,7 +41,6 @@ namespace MediaBrowser.Controller.Entities.Movies
public List<Guid> LocalTrailerIds { get; set; }
public List<Guid> RemoteTrailerIds { get; set; }
- public List<string> Keywords { get; set; }
public List<MediaUrl> RemoteTrailers { get; set; }
@@ -77,45 +74,6 @@ namespace MediaBrowser.Controller.Entities.Movies
get { return TmdbCollectionName; }
set { TmdbCollectionName = value; }
}
-
- /// <summary>
- /// Gets the trailer ids.
- /// </summary>
- /// <returns>List&lt;Guid&gt;.</returns>
- public List<Guid> GetTrailerIds()
- {
- var list = LocalTrailerIds.ToList();
- list.AddRange(RemoteTrailerIds);
- return list;
- }
-
- /// <summary>
- /// Gets the user data key.
- /// </summary>
- /// <returns>System.String.</returns>
- protected override string CreateUserDataKey()
- {
- var key = GetMovieUserDataKey(this);
-
- if (string.IsNullOrWhiteSpace(key))
- {
- key = base.CreateUserDataKey();
- }
-
- return key;
- }
-
- public static string GetMovieUserDataKey(BaseItem movie)
- {
- var key = movie.GetProviderId(MetadataProviders.Tmdb);
-
- if (string.IsNullOrWhiteSpace(key))
- {
- key = movie.GetProviderId(MetadataProviders.Imdb);
- }
-
- return key;
- }
protected override async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, List<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
{
@@ -204,5 +162,22 @@ namespace MediaBrowser.Controller.Entities.Movies
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;
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/MusicVideo.cs b/MediaBrowser.Controller/Entities/MusicVideo.cs
index b52f16a46..7119828e2 100644
--- a/MediaBrowser.Controller/Entities/MusicVideo.cs
+++ b/MediaBrowser.Controller/Entities/MusicVideo.cs
@@ -10,12 +10,6 @@ namespace MediaBrowser.Controller.Entities
public class MusicVideo : Video, IHasArtist, IHasMusicGenres, IHasProductionLocations, IHasBudget, IHasLookupInfo<MusicVideoInfo>
{
/// <summary>
- /// Gets or sets the album.
- /// </summary>
- /// <value>The album.</value>
- public string Album { get; set; }
-
- /// <summary>
/// Gets or sets the budget.
/// </summary>
/// <value>The budget.</value>
@@ -44,15 +38,6 @@ namespace MediaBrowser.Controller.Entities
}
}
- /// <summary>
- /// Gets the user data key.
- /// </summary>
- /// <returns>System.String.</returns>
- protected override string CreateUserDataKey()
- {
- return this.GetProviderId(MetadataProviders.Tmdb) ?? this.GetProviderId(MetadataProviders.Imdb) ?? base.CreateUserDataKey();
- }
-
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.Music;
diff --git a/MediaBrowser.Controller/Entities/Person.cs b/MediaBrowser.Controller/Entities/Person.cs
index 560ea6e05..8ef0d70bf 100644
--- a/MediaBrowser.Controller/Entities/Person.cs
+++ b/MediaBrowser.Controller/Entities/Person.cs
@@ -3,6 +3,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Controller.Entities
@@ -18,13 +19,20 @@ namespace MediaBrowser.Controller.Entities
/// <value>The place of birth.</value>
public string PlaceOfBirth { get; set; }
- /// <summary>
- /// Gets the user data key.
- /// </summary>
- /// <returns>System.String.</returns>
- protected override string CreateUserDataKey()
+ public override List<string> GetUserDataKeys()
{
- return "Person-" + Name;
+ var list = base.GetUserDataKeys();
+
+ list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
+ return list;
+ }
+
+ public override string PresentationUniqueKey
+ {
+ get
+ {
+ return GetUserDataKeys()[0];
+ }
}
public PersonLookupInfo GetLookupInfo()
@@ -32,6 +40,13 @@ namespace MediaBrowser.Controller.Entities
return GetItemLookupInfo<PersonLookupInfo>();
}
+ public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
+ {
+ query.Person = Name;
+
+ return LibraryManager.GetItemList(query);
+ }
+
/// <summary>
/// Returns the folder containing the item.
/// If the item is a folder, it returns the folder itself
diff --git a/MediaBrowser.Controller/Entities/Photo.cs b/MediaBrowser.Controller/Entities/Photo.cs
index 3358ccc6f..804ea04a5 100644
--- a/MediaBrowser.Controller/Entities/Photo.cs
+++ b/MediaBrowser.Controller/Entities/Photo.cs
@@ -5,7 +5,7 @@ using System.Runtime.Serialization;
namespace MediaBrowser.Controller.Entities
{
- public class Photo : BaseItem, IHasTags, IHasTaglines
+ public class Photo : BaseItem, IHasTaglines
{
public List<string> Taglines { get; set; }
@@ -51,6 +51,12 @@ namespace MediaBrowser.Controller.Entities
}
}
+ [IgnoreDataMember]
+ public override bool EnableForceSaveOnDateModifiedChange
+ {
+ get { return true; }
+ }
+
public override bool CanDownload()
{
return true;
diff --git a/MediaBrowser.Controller/Entities/PhotoAlbum.cs b/MediaBrowser.Controller/Entities/PhotoAlbum.cs
index c8ab67a69..b0ddcfb8c 100644
--- a/MediaBrowser.Controller/Entities/PhotoAlbum.cs
+++ b/MediaBrowser.Controller/Entities/PhotoAlbum.cs
@@ -8,15 +8,6 @@ namespace MediaBrowser.Controller.Entities
public class PhotoAlbum : Folder
{
[IgnoreDataMember]
- public override bool SupportsLocalMetadata
- {
- get
- {
- return false;
- }
- }
-
- [IgnoreDataMember]
public override bool AlwaysScanInternalMetadataPath
{
get
diff --git a/MediaBrowser.Controller/Entities/Studio.cs b/MediaBrowser.Controller/Entities/Studio.cs
index a55527f37..762798b55 100644
--- a/MediaBrowser.Controller/Entities/Studio.cs
+++ b/MediaBrowser.Controller/Entities/Studio.cs
@@ -2,21 +2,29 @@
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
+using MediaBrowser.Common.Extensions;
namespace MediaBrowser.Controller.Entities
{
/// <summary>
/// Class Studio
/// </summary>
- public class Studio : BaseItem, IItemByName, IHasTags
+ public class Studio : BaseItem, IItemByName
{
- /// <summary>
- /// Gets the user data key.
- /// </summary>
- /// <returns>System.String.</returns>
- protected override string CreateUserDataKey()
+ public override List<string> GetUserDataKeys()
{
- return "Studio-" + Name;
+ var list = base.GetUserDataKeys();
+
+ list.Insert(0, GetType().Name + "-" + (Name ?? string.Empty).RemoveDiacritics());
+ return list;
+ }
+
+ public override string PresentationUniqueKey
+ {
+ get
+ {
+ return GetUserDataKeys()[0];
+ }
}
/// <summary>
@@ -66,6 +74,13 @@ namespace MediaBrowser.Controller.Entities
return i => i.Studios.Contains(Name, StringComparer.OrdinalIgnoreCase);
}
+ public IEnumerable<BaseItem> GetTaggedItems(InternalItemsQuery query)
+ {
+ query.Studios = new[] { Name };
+
+ return LibraryManager.GetItemList(query);
+ }
+
[IgnoreDataMember]
public override bool SupportsPeople
{
diff --git a/MediaBrowser.Controller/Entities/TV/Episode.cs b/MediaBrowser.Controller/Entities/TV/Episode.cs
index 88dae3c7c..726390f65 100644
--- a/MediaBrowser.Controller/Entities/TV/Episode.cs
+++ b/MediaBrowser.Controller/Entities/TV/Episode.cs
@@ -11,8 +11,19 @@ namespace MediaBrowser.Controller.Entities.TV
/// <summary>
/// Class Episode
/// </summary>
- public class Episode : Video, IHasLookupInfo<EpisodeInfo>, IHasSeries
- {
+ public class Episode : Video, IHasTrailers, IHasLookupInfo<EpisodeInfo>, IHasSeries
+ {
+ public Episode()
+ {
+ RemoteTrailers = new List<MediaUrl>();
+ LocalTrailerIds = new List<Guid>();
+ RemoteTrailerIds = new List<Guid>();
+ }
+
+ public List<Guid> LocalTrailerIds { get; set; }
+ public List<Guid> RemoteTrailerIds { get; set; }
+ public List<MediaUrl> RemoteTrailers { get; set; }
+
/// <summary>
/// Gets the season in which it aired.
/// </summary>
@@ -42,7 +53,16 @@ namespace MediaBrowser.Controller.Entities.TV
/// This is the ending episode number for double episodes.
/// </summary>
/// <value>The index number.</value>
- public int? IndexNumberEnd { get; set; }
+ public int? IndexNumberEnd { get; set; }
+
+ [IgnoreDataMember]
+ public string SeriesSortName { get; set; }
+
+ public string FindSeriesSortName()
+ {
+ var series = Series;
+ return series == null ? SeriesSortName : series.SortName;
+ }
[IgnoreDataMember]
protected override bool SupportsOwnedItems
@@ -58,60 +78,54 @@ namespace MediaBrowser.Controller.Entities.TV
{
get
{
- return AirsAfterSeasonNumber ?? AirsBeforeSeasonNumber ?? PhysicalSeasonNumber;
+ return AirsAfterSeasonNumber ?? AirsBeforeSeasonNumber ?? ParentIndexNumber;
}
}
[IgnoreDataMember]
- public int? PhysicalSeasonNumber
+ public override Folder LatestItemsIndexContainer
{
get
{
- var value = ParentIndexNumber;
-
- if (value.HasValue)
- {
- return value;
- }
-
- var season = Season;
-
- return season != null ? season.IndexNumber : null;
+ return Series;
}
}
[IgnoreDataMember]
- public override Folder LatestItemsIndexContainer
+ public override Guid? DisplayParentId
{
get
{
- return Series;
+ return SeasonId;
}
}
[IgnoreDataMember]
- public override BaseItem DisplayParent
+ protected override bool EnableDefaultVideoUserDataKeys
{
get
{
- return Season ?? GetParent();
+ return false;
}
}
- /// <summary>
- /// Gets the user data key.
- /// </summary>
- /// <returns>System.String.</returns>
- protected override string CreateUserDataKey()
+ public override List<string> GetUserDataKeys()
{
- var series = Series;
+ var list = base.GetUserDataKeys();
+ var series = Series;
if (series != null && ParentIndexNumber.HasValue && IndexNumber.HasValue)
{
- return series.GetUserDataKey() + ParentIndexNumber.Value.ToString("000") + IndexNumber.Value.ToString("000");
+ 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 base.CreateUserDataKey();
+ return list;
}
/// <summary>
@@ -160,13 +174,27 @@ namespace MediaBrowser.Controller.Entities.TV
}
[IgnoreDataMember]
- public string SeriesName
- {
- get
- {
- var series = Series;
- return series == null ? null : series.Name;
- }
+ public string SeriesName { get; set; }
+
+ [IgnoreDataMember]
+ public string SeasonName { get; set; }
+
+ public string FindSeasonName()
+ {
+ var season = Season;
+ return season == null ? SeasonName : season.Name;
+ }
+
+ public string FindSeriesName()
+ {
+ var series = Series;
+ return series == null ? SeriesName : series.Name;
+ }
+
+ public Guid? FindSeasonId()
+ {
+ var season = Season;
+ return season == null ? (Guid?)null : season.Id;
}
/// <summary>
@@ -175,7 +203,7 @@ namespace MediaBrowser.Controller.Entities.TV
/// <returns>System.String.</returns>
protected override string CreateSortName()
{
- return (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("000-") : "")
+ return (ParentIndexNumber != null ? ParentIndexNumber.Value.ToString("000 - ") : "")
+ (IndexNumber != null ? IndexNumber.Value.ToString("0000 - ") : "") + Name;
}
@@ -223,32 +251,20 @@ namespace MediaBrowser.Controller.Entities.TV
}
[IgnoreDataMember]
- public bool IsUnaired
- {
- get { return PremiereDate.HasValue && PremiereDate.Value.ToLocalTime().Date >= DateTime.Now.Date; }
- }
-
- [IgnoreDataMember]
public bool IsVirtualUnaired
{
get { return LocationType == LocationType.Virtual && IsUnaired; }
}
[IgnoreDataMember]
- public Guid? SeasonId
- {
- get
- {
- // First see if the parent is a Season
- var season = Season;
-
- if (season != null)
- {
- return season.Id;
- }
-
- return null;
- }
+ public Guid? SeasonId { get; set; }
+ [IgnoreDataMember]
+ public Guid? SeriesId { get; set; }
+
+ public Guid? FindSeriesId()
+ {
+ var series = Series;
+ return series == null ? (Guid?)null : series.Id;
}
public override IEnumerable<Guid> GetAncestorIds()
@@ -287,7 +303,9 @@ namespace MediaBrowser.Controller.Entities.TV
id.AnimeSeriesIndex = series.AnimeSeriesIndex;
}
+ id.IsMissingEpisode = IsMissingEpisode;
id.IndexNumberEnd = IndexNumberEnd;
+ id.IsVirtualUnaired = IsVirtualUnaired;
return id;
}
@@ -308,6 +326,19 @@ namespace MediaBrowser.Controller.Entities.TV
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
index 9efa609ef..ee01c60b1 100644
--- a/MediaBrowser.Controller/Entities/TV/Season.cs
+++ b/MediaBrowser.Controller/Entities/TV/Season.cs
@@ -33,35 +33,60 @@ namespace MediaBrowser.Controller.Entities.TV
}
[IgnoreDataMember]
- public override BaseItem DisplayParent
+ public override bool SupportsDateLastMediaAdded
{
- get { return Series ?? GetParent(); }
+ get
+ {
+ return true;
+ }
+ }
+
+ [IgnoreDataMember]
+ public override Guid? DisplayParentId
+ {
+ get
+ {
+ var series = Series;
+ return series == null ? ParentId : series.Id;
+ }
+ }
+
+ [IgnoreDataMember]
+ public string SeriesSortName { get; set; }
+
+ public string FindSeriesSortName()
+ {
+ var series = Series;
+ return series == null ? SeriesSortName : series.SortName;
}
// Genre, Rating and Stuido will all be the same
protected override IEnumerable<string> GetIndexByOptions()
{
- return new List<string> {
- {"None"},
+ return new List<string> {
+ {"None"},
{"Performer"},
{"Director"},
{"Year"},
};
}
- /// <summary>
- /// Gets the user data key.
- /// </summary>
- /// <returns>System.String.</returns>
- protected override string CreateUserDataKey()
+ public override List<string> GetUserDataKeys()
{
- if (Series != null)
+ var list = base.GetUserDataKeys();
+
+ var series = Series;
+ if (series != null)
{
- var seasonNo = IndexNumber ?? 0;
- return Series.GetUserDataKey() + seasonNo.ToString("000");
+ list.InsertRange(0, series.GetUserDataKeys().Select(i => i + (IndexNumber ?? 0).ToString("000")));
}
- return base.CreateUserDataKey();
+ return list;
+ }
+
+ public override int GetChildCount(User user)
+ {
+ return GetChildren(user, true).Count();
}
/// <summary>
@@ -90,6 +115,24 @@ namespace MediaBrowser.Controller.Entities.TV
}
}
+ [IgnoreDataMember]
+ public override string PresentationUniqueKey
+ {
+ get
+ {
+ if (IndexNumber.HasValue)
+ {
+ var series = Series;
+ if (series != null)
+ {
+ return series.PresentationUniqueKey + "-" + (IndexNumber ?? 0).ToString("000");
+ }
+ }
+
+ return base.PresentationUniqueKey;
+ }
+ }
+
/// <summary>
/// Creates the name of the sort.
/// </summary>
@@ -102,25 +145,13 @@ namespace MediaBrowser.Controller.Entities.TV
[IgnoreDataMember]
public bool IsMissingSeason
{
- get { return LocationType == LocationType.Virtual && GetEpisodes().All(i => i.IsMissingEpisode); }
- }
-
- [IgnoreDataMember]
- public bool IsUnaired
- {
- get { return GetEpisodes().All(i => i.IsUnaired); }
+ get { return (IsVirtualItem) && !IsUnaired; }
}
[IgnoreDataMember]
public bool IsVirtualUnaired
{
- get { return LocationType == LocationType.Virtual && IsUnaired; }
- }
-
- [IgnoreDataMember]
- public bool IsMissingOrVirtualUnaired
- {
- get { return LocationType == LocationType.Virtual && GetEpisodes().All(i => i.IsVirtualUnaired || i.IsMissingEpisode); }
+ get { return (IsVirtualItem) && IsUnaired; }
}
[IgnoreDataMember]
@@ -129,24 +160,18 @@ namespace MediaBrowser.Controller.Entities.TV
get { return (IndexNumber ?? -1) == 0; }
}
- public override Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
+ protected override Task<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);
- IEnumerable<BaseItem> items;
-
- if (query.User == null)
- {
- items = query.Recursive
- ? GetRecursiveChildren(filter)
- : Children.Where(filter);
- }
- else
- {
- items = GetEpisodes(query.User).Where(filter);
- }
+ var items = GetEpisodes(user).Where(filter);
var result = PostFilterAndSort(items, query);
@@ -162,55 +187,20 @@ namespace MediaBrowser.Controller.Entities.TV
{
var config = user.Configuration;
- return GetEpisodes(user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
+ return GetEpisodes(Series, user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
}
- public IEnumerable<Episode> GetEpisodes(User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
+ public IEnumerable<Episode> GetEpisodes(Series series, User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
{
- var episodes = GetRecursiveChildren(user)
- .OfType<Episode>();
-
- var series = Series;
-
- if (IndexNumber.HasValue && series != null)
- {
- return series.GetEpisodes(user, IndexNumber.Value, includeMissingEpisodes, includeVirtualUnairedEpisodes, episodes);
- }
-
- if (series != null && series.ContainsEpisodesWithoutSeasonFolders)
- {
- var seasonNumber = IndexNumber;
- var list = episodes.ToList();
-
- if (seasonNumber.HasValue)
- {
- list.AddRange(series.GetRecursiveChildren(user).OfType<Episode>()
- .Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber.Value));
- }
- else
- {
- list.AddRange(series.GetRecursiveChildren(user).OfType<Episode>()
- .Where(i => !i.ParentIndexNumber.HasValue));
- }
-
- episodes = list.DistinctBy(i => i.Id);
- }
-
- if (!includeMissingEpisodes)
- {
- episodes = episodes.Where(i => !i.IsMissingEpisode);
- }
- if (!includeVirtualUnairedEpisodes)
- {
- episodes = episodes.Where(i => !i.IsVirtualUnaired);
- }
+ return GetEpisodes(series, user, includeMissingEpisodes, includeVirtualUnairedEpisodes, null);
+ }
- return LibraryManager
- .Sort(episodes, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending)
- .Cast<Episode>();
+ public IEnumerable<Episode> GetEpisodes(Series series, User user, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable<Episode> allSeriesEpisodes)
+ {
+ return series.GetEpisodes(user, this, includeMissingEpisodes, includeVirtualUnairedEpisodes, allSeriesEpisodes);
}
- private IEnumerable<Episode> GetEpisodes()
+ public IEnumerable<Episode> GetEpisodes()
{
var episodes = GetRecursiveChildren().OfType<Episode>();
var series = Series;
@@ -254,13 +244,21 @@ namespace MediaBrowser.Controller.Entities.TV
}
[IgnoreDataMember]
- public string SeriesName
+ public string SeriesName { get; set; }
+
+ [IgnoreDataMember]
+ public Guid? SeriesId { get; set; }
+
+ public string FindSeriesName()
{
- get
- {
- var series = Series;
- return series == null ? null : series.Name;
- }
+ var series = Series;
+ return series == null ? SeriesName : series.Name;
+ }
+
+ public Guid? FindSeriesId()
+ {
+ var series = Series;
+ return series == null ? (Guid?)null : series.Id;
}
/// <summary>
@@ -290,19 +288,14 @@ namespace MediaBrowser.Controller.Entities.TV
{
var hasChanges = base.BeforeMetadataRefresh();
- var locationType = LocationType;
-
- if (locationType == LocationType.FileSystem || locationType == LocationType.Offline)
+ if (!IndexNumber.HasValue && !string.IsNullOrEmpty(Path))
{
- if (!IndexNumber.HasValue && !string.IsNullOrEmpty(Path))
- {
- IndexNumber = IndexNumber ?? LibraryManager.GetSeasonNumberFromPath(Path);
+ IndexNumber = IndexNumber ?? LibraryManager.GetSeasonNumberFromPath(Path);
- // If a change was made record it
- if (IndexNumber.HasValue)
- {
- hasChanges = true;
- }
+ // If a change was made record it
+ if (IndexNumber.HasValue)
+ {
+ hasChanges = true;
}
}
diff --git a/MediaBrowser.Controller/Entities/TV/Series.cs b/MediaBrowser.Controller/Entities/TV/Series.cs
index aa07ab378..ad35b3d36 100644
--- a/MediaBrowser.Controller/Entities/TV/Series.cs
+++ b/MediaBrowser.Controller/Entities/TV/Series.cs
@@ -9,6 +9,8 @@ using System.Linq;
using System.Runtime.Serialization;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Model.Providers;
+using MoreLinq;
namespace MediaBrowser.Controller.Entities.TV
{
@@ -19,8 +21,6 @@ namespace MediaBrowser.Controller.Entities.TV
{
public List<Guid> SpecialFeatureIds { get; set; }
- public string OriginalTitle { get; set; }
-
public int? AnimeSeriesIndex { get; set; }
public Series()
@@ -31,7 +31,6 @@ namespace MediaBrowser.Controller.Entities.TV
RemoteTrailers = new List<MediaUrl>();
LocalTrailerIds = new List<Guid>();
RemoteTrailerIds = new List<Guid>();
- DisplaySpecialsWithSeasons = true;
}
[IgnoreDataMember]
@@ -49,7 +48,14 @@ namespace MediaBrowser.Controller.Entities.TV
}
}
- public bool DisplaySpecialsWithSeasons { get; set; }
+ [IgnoreDataMember]
+ public override bool SupportsDateLastMediaAdded
+ {
+ get
+ {
+ return true;
+ }
+ }
public List<Guid> LocalTrailerIds { get; set; }
public List<Guid> RemoteTrailerIds { get; set; }
@@ -86,32 +92,69 @@ namespace MediaBrowser.Controller.Entities.TV
{
get
{
- return GetRecursiveChildren(i => i is Episode)
- .Select(i => i.DateCreated)
- .OrderByDescending(i => i)
- .FirstOrDefault();
+ return DateLastMediaAdded ?? DateTime.MinValue;
}
}
+ [IgnoreDataMember]
+ public override string PresentationUniqueKey
+ {
+ get
+ {
+ var userdatakeys = GetUserDataKeys();
+
+ if (userdatakeys.Count > 1)
+ {
+ return userdatakeys[0];
+ }
+ return base.PresentationUniqueKey;
+ }
+ }
+
+ private static string GetUniqueSeriesKey(BaseItem series)
+ {
+ if (ConfigurationManager.Configuration.SchemaVersion < 97)
+ {
+ return series.Id.ToString("N");
+ }
+ return series.PresentationUniqueKey;
+ }
+
+ public override int GetChildCount(User user)
+ {
+ var result = LibraryManager.GetItemsResult(new InternalItemsQuery(user)
+ {
+ AncestorWithPresentationUniqueKey = GetUniqueSeriesKey(this),
+ IncludeItemTypes = new[] { typeof(Season).Name },
+ SortBy = new[] { ItemSortBy.SortName },
+ IsVirtualItem = false,
+ Limit = 0
+ });
+
+ return result.TotalRecordCount;
+ }
+
/// <summary>
/// Gets the user data key.
/// </summary>
/// <returns>System.String.</returns>
- protected override string CreateUserDataKey()
+ public override List<string> GetUserDataKeys()
{
- var key = this.GetProviderId(MetadataProviders.Tvdb);
+ var list = base.GetUserDataKeys();
- if (string.IsNullOrWhiteSpace(key))
+ var key = this.GetProviderId(MetadataProviders.Imdb);
+ if (!string.IsNullOrWhiteSpace(key))
{
- key = this.GetProviderId(MetadataProviders.Imdb);
+ list.Insert(0, key);
}
- if (string.IsNullOrWhiteSpace(key))
+ key = this.GetProviderId(MetadataProviders.Tvdb);
+ if (!string.IsNullOrWhiteSpace(key))
{
- key = base.CreateUserDataKey();
+ list.Insert(0, key);
}
- return key;
+ return list;
}
/// <summary>
@@ -128,8 +171,8 @@ namespace MediaBrowser.Controller.Entities.TV
// Studio, Genre and Rating will all be the same so makes no sense to index by these
protected override IEnumerable<string> GetIndexByOptions()
{
- return new List<string> {
- {"None"},
+ return new List<string> {
+ {"None"},
{"Performer"},
{"Director"},
{"Year"},
@@ -157,56 +200,59 @@ namespace MediaBrowser.Controller.Entities.TV
return GetSeasons(user, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
}
- public override Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
+ protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery 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);
+ return base.GetItemsInternal(query);
}
- else
+
+ var user = query.User;
+
+ if (query.Recursive)
{
- items = query.Recursive
- ? GetRecursiveChildren(user, filter)
- : GetSeasons(user).Where(filter);
+ query.AncestorWithPresentationUniqueKey = GetUniqueSeriesKey(this);
+ if (query.SortBy.Length == 0)
+ {
+ query.SortBy = new[] { ItemSortBy.SortName };
+ }
+ if (query.IncludeItemTypes.Length == 0)
+ {
+ query.IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name };
+ }
+ query.IsVirtualItem = false;
+ return Task.FromResult(LibraryManager.GetItemsResult(query));
}
- var result = PostFilterAndSort(items, query);
+ Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
+ var items = GetSeasons(user).Where(filter);
+ var result = PostFilterAndSort(items, query);
return Task.FromResult(result);
}
public IEnumerable<Season> GetSeasons(User user, bool includeMissingSeasons, bool includeVirtualUnaired)
{
- var seasons = base.GetChildren(user, true)
- .OfType<Season>();
+ IEnumerable<Season> seasons;
+
+ seasons = LibraryManager.GetItemList(new InternalItemsQuery(user)
+ {
+ AncestorWithPresentationUniqueKey = GetUniqueSeriesKey(this),
+ IncludeItemTypes = new[] { typeof(Season).Name },
+ SortBy = new[] { ItemSortBy.SortName }
+
+ }).Cast<Season>();
- if (!includeMissingSeasons && !includeVirtualUnaired)
+ if (!includeMissingSeasons)
{
- seasons = seasons.Where(i => !i.IsMissingOrVirtualUnaired);
+ seasons = seasons.Where(i => !(i.IsMissingSeason));
}
- else
+ if (!includeVirtualUnaired)
{
- if (!includeMissingSeasons)
- {
- seasons = seasons.Where(i => !i.IsMissingSeason);
- }
- if (!includeVirtualUnaired)
- {
- seasons = seasons.Where(i => !i.IsVirtualUnaired);
- }
+ seasons = seasons.Where(i => !i.IsVirtualUnaired);
}
- return LibraryManager
- .Sort(seasons, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending)
- .Cast<Season>();
+ return seasons;
}
public IEnumerable<Episode> GetEpisodes(User user)
@@ -218,25 +264,26 @@ namespace MediaBrowser.Controller.Entities.TV
public IEnumerable<Episode> GetEpisodes(User user, bool includeMissing, bool includeVirtualUnaired)
{
- var allEpisodes = GetSeasons(user, true, true)
- .SelectMany(i => i.GetEpisodes(user, includeMissing, includeVirtualUnaired))
+ var allItems = LibraryManager.GetItemList(new InternalItemsQuery(user)
+ {
+ AncestorWithPresentationUniqueKey = GetUniqueSeriesKey(this),
+ IncludeItemTypes = new[] { typeof(Episode).Name, typeof(Season).Name },
+ SortBy = new[] { ItemSortBy.SortName }
+
+ }).ToList();
+
+ var allSeriesEpisodes = allItems.OfType<Episode>().ToList();
+
+ var allEpisodes = allItems.OfType<Season>()
+ .SelectMany(i => i.GetEpisodes(this, user, includeMissing, includeVirtualUnaired, allSeriesEpisodes))
.Reverse()
.ToList();
// 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
- var returnList = new List<Episode>();
-
- foreach (var episode in allEpisodes)
- {
- if (!returnList.Contains(episode))
- {
- returnList.Insert(0, episode);
- }
- }
- return returnList;
+ return allEpisodes.DistinctBy(i => i.Id).Reverse();
}
public async Task RefreshAllMetadata(MetadataRefreshOptions refreshOptions, IProgress<double> progress, CancellationToken cancellationToken)
@@ -251,13 +298,10 @@ namespace MediaBrowser.Controller.Entities.TV
var totalItems = seasons.Count + otherItems.Count;
var numComplete = 0;
- refreshOptions = new MetadataRefreshOptions(refreshOptions);
- refreshOptions.IsPostRecursiveRefresh = true;
-
// Refresh current item
await RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
- // Refresh TV
+ // Refresh seasons
foreach (var item in seasons)
{
cancellationToken.ThrowIfCancellationRequested();
@@ -270,12 +314,30 @@ namespace MediaBrowser.Controller.Entities.TV
progress.Report(percent * 100);
}
- // Refresh all non-songs
+ // Refresh episodes and other children
foreach (var item in otherItems)
{
cancellationToken.ThrowIfCancellationRequested();
- await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
+ 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)
+ {
+ await item.RefreshMetadata(refreshOptions, cancellationToken).ConfigureAwait(false);
+ }
numComplete++;
double percent = numComplete;
@@ -283,32 +345,46 @@ namespace MediaBrowser.Controller.Entities.TV
progress.Report(percent * 100);
}
+ refreshOptions = new MetadataRefreshOptions(refreshOptions);
+ refreshOptions.IsPostRecursiveRefresh = true;
await ProviderManager.RefreshSingleItem(this, refreshOptions, cancellationToken).ConfigureAwait(false);
progress.Report(100);
}
- public IEnumerable<Episode> GetEpisodes(User user, int seasonNumber)
+ public IEnumerable<Episode> GetEpisodes(User user, Season season)
{
var config = user.Configuration;
- return GetEpisodes(user, seasonNumber, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
+ return GetEpisodes(user, season, config.DisplayMissingEpisodes, config.DisplayUnairedEpisodes);
}
- public IEnumerable<Episode> GetEpisodes(User user, int seasonNumber, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
+ private IEnumerable<Episode> GetAllEpisodes(User user)
{
- return GetEpisodes(user, seasonNumber, includeMissingEpisodes, includeVirtualUnairedEpisodes,
- new List<Episode>());
+ return LibraryManager.GetItemList(new InternalItemsQuery(user)
+ {
+ AncestorWithPresentationUniqueKey = GetUniqueSeriesKey(this),
+ IncludeItemTypes = new[] { typeof(Episode).Name },
+ SortBy = new[] { ItemSortBy.SortName }
+
+ }).Cast<Episode>();
}
- internal IEnumerable<Episode> GetEpisodes(User user, int seasonNumber, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable<Episode> additionalEpisodes)
+ public IEnumerable<Episode> GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes)
{
- var episodes = GetRecursiveChildren(user, i => i is Episode)
- .Cast<Episode>();
+ IEnumerable<Episode> episodes = GetAllEpisodes(user);
- episodes = FilterEpisodesBySeason(episodes, seasonNumber, DisplaySpecialsWithSeasons);
+ return GetEpisodes(user, parentSeason, includeMissingEpisodes, includeVirtualUnairedEpisodes, episodes);
+ }
- episodes = episodes.Concat(additionalEpisodes).Distinct();
+ public IEnumerable<Episode> GetEpisodes(User user, Season parentSeason, bool includeMissingEpisodes, bool includeVirtualUnairedEpisodes, IEnumerable<Episode> allSeriesEpisodes)
+ {
+ if (allSeriesEpisodes == null)
+ {
+ return GetEpisodes(user, parentSeason, includeMissingEpisodes, includeVirtualUnairedEpisodes);
+ }
+
+ var episodes = FilterEpisodesBySeason(allSeriesEpisodes, parentSeason, ConfigurationManager.Configuration.DisplaySpecialsWithinSeasons);
if (!includeMissingEpisodes)
{
@@ -319,7 +395,7 @@ namespace MediaBrowser.Controller.Entities.TV
episodes = episodes.Where(i => !i.IsVirtualUnaired);
}
- var sortBy = seasonNumber == 0 ? ItemSortBy.SortName : ItemSortBy.AiredEpisodeOrder;
+ var sortBy = (parentSeason.IndexNumber ?? -1) == 0 ? ItemSortBy.SortName : ItemSortBy.AiredEpisodeOrder;
return LibraryManager.Sort(episodes, user, new[] { sortBy }, SortOrder.Ascending)
.Cast<Episode>();
@@ -328,15 +404,11 @@ namespace MediaBrowser.Controller.Entities.TV
/// <summary>
/// Filters the episodes by season.
/// </summary>
- /// <param name="episodes">The episodes.</param>
- /// <param name="seasonNumber">The season number.</param>
- /// <param name="includeSpecials">if set to <c>true</c> [include specials].</param>
- /// <returns>IEnumerable{Episode}.</returns>
public static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> episodes, int seasonNumber, bool includeSpecials)
{
if (!includeSpecials || seasonNumber < 1)
{
- return episodes.Where(i => (i.PhysicalSeasonNumber ?? -1) == seasonNumber);
+ return episodes.Where(i => (i.ParentIndexNumber ?? -1) == seasonNumber);
}
return episodes.Where(i =>
@@ -354,6 +426,34 @@ namespace MediaBrowser.Controller.Entities.TV
});
}
+ /// <summary>
+ /// Filters the episodes by season.
+ /// </summary>
+ public static IEnumerable<Episode> FilterEpisodesBySeason(IEnumerable<Episode> 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 currentSeasonNumber = supportSpecialsInSeason ? episode.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 = episode.Season;
+ return season != null && string.Equals(GetUniqueSeriesKey(season), seasonPresentationKey, StringComparison.OrdinalIgnoreCase);
+ });
+ }
+
protected override bool GetBlockUnratedValue(UserPolicy config)
{
return config.BlockUnratedItems.Contains(UnratedItem.Series);
@@ -392,5 +492,22 @@ namespace MediaBrowser.Controller.Entities.TV
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;
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/IHasTags.cs b/MediaBrowser.Controller/Entities/TagExtensions.cs
index 45a56009d..0e1df72cd 100644
--- a/MediaBrowser.Controller/Entities/IHasTags.cs
+++ b/MediaBrowser.Controller/Entities/TagExtensions.cs
@@ -1,24 +1,11 @@
using System;
-using System.Collections.Generic;
using System.Linq;
namespace MediaBrowser.Controller.Entities
{
- /// <summary>
- /// Interface IHasTags
- /// </summary>
- public interface IHasTags
- {
- /// <summary>
- /// Gets or sets the tags.
- /// </summary>
- /// <value>The tags.</value>
- List<string> Tags { get; set; }
- }
-
public static class TagExtensions
{
- public static void AddTag(this IHasTags item, string name)
+ public static void AddTag(this BaseItem item, string name)
{
if (string.IsNullOrWhiteSpace(name))
{
diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs
index bd7d30858..eab5ab679 100644
--- a/MediaBrowser.Controller/Entities/Trailer.cs
+++ b/MediaBrowser.Controller/Entities/Trailer.cs
@@ -5,13 +5,14 @@ using System.Collections.Generic;
using System.Globalization;
using System.Runtime.Serialization;
using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Model.Providers;
namespace MediaBrowser.Controller.Entities
{
/// <summary>
/// Class Trailer
/// </summary>
- public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasKeywords, IHasTaglines, IHasMetascore, IHasLookupInfo<TrailerInfo>
+ public class Trailer : Video, IHasCriticRating, IHasProductionLocations, IHasBudget, IHasTaglines, IHasMetascore, IHasOriginalTitle, IHasLookupInfo<TrailerInfo>
{
public List<string> ProductionLocations { get; set; }
@@ -21,17 +22,15 @@ namespace MediaBrowser.Controller.Entities
Taglines = new List<string>();
Keywords = new List<string>();
ProductionLocations = new List<string>();
- TrailerTypes = new List<TrailerType>();
+ TrailerTypes = new List<TrailerType> { TrailerType.LocalTrailer };
}
public List<TrailerType> TrailerTypes { get; set; }
-
+
public float? Metascore { get; set; }
public List<MediaUrl> RemoteTrailers { get; set; }
- public List<string> Keywords { get; set; }
-
[IgnoreDataMember]
public bool IsLocalTrailer
{
@@ -56,26 +55,6 @@ namespace MediaBrowser.Controller.Entities
/// <value>The revenue.</value>
public double? Revenue { get; set; }
- protected override string CreateUserDataKey()
- {
- var key = Movie.GetMovieUserDataKey(this);
-
- if (!string.IsNullOrWhiteSpace(key))
- {
- key = key + "-trailer";
-
- // Make sure different trailers have their own data.
- if (RunTimeTicks.HasValue)
- {
- key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture);
- }
-
- return key;
- }
-
- return base.CreateUserDataKey();
- }
-
public override UnratedItem GetBlockUnratedType()
{
return UnratedItem.Trailer;
@@ -86,7 +65,7 @@ namespace MediaBrowser.Controller.Entities
var info = GetItemLookupInfo<TrailerInfo>();
info.IsLocalTrailer = TrailerTypes.Contains(TrailerType.LocalTrailer);
-
+
if (!IsInMixedFolder)
{
info.Name = System.IO.Path.GetFileName(ContainingFolderPath);
@@ -130,5 +109,22 @@ namespace MediaBrowser.Controller.Entities
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;
+ }
}
}
diff --git a/MediaBrowser.Controller/Entities/User.cs b/MediaBrowser.Controller/Entities/User.cs
index e5b39003d..5c68308f5 100644
--- a/MediaBrowser.Controller/Entities/User.cs
+++ b/MediaBrowser.Controller/Entities/User.cs
@@ -305,14 +305,7 @@ namespace MediaBrowser.Controller.Entities
public bool IsFolderGrouped(Guid id)
{
- var config = Configuration;
-
- if (config.ExcludeFoldersFromGrouping != null)
- {
- return !config.ExcludeFoldersFromGrouping.Select(i => new Guid(i)).Contains(id);
- }
-
- return config.GroupedFolders.Select(i => new Guid(i)).Contains(id);
+ return Configuration.GroupedFolders.Select(i => new Guid(i)).Contains(id);
}
[IgnoreDataMember]
diff --git a/MediaBrowser.Controller/Entities/UserItemData.cs b/MediaBrowser.Controller/Entities/UserItemData.cs
index 16c37e7d3..f95fd7036 100644
--- a/MediaBrowser.Controller/Entities/UserItemData.cs
+++ b/MediaBrowser.Controller/Entities/UserItemData.cs
@@ -88,6 +88,8 @@ namespace MediaBrowser.Controller.Entities
/// </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
@@ -101,7 +103,7 @@ namespace MediaBrowser.Controller.Entities
{
if (Rating != null)
{
- return Rating >= 6.5;
+ return Rating >= MinLikeValue;
}
return null;
diff --git a/MediaBrowser.Controller/Entities/UserRootFolder.cs b/MediaBrowser.Controller/Entities/UserRootFolder.cs
index 104408860..8e6f11c2c 100644
--- a/MediaBrowser.Controller/Entities/UserRootFolder.cs
+++ b/MediaBrowser.Controller/Entities/UserRootFolder.cs
@@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Controller.Library;
namespace MediaBrowser.Controller.Entities
{
@@ -17,7 +18,7 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class UserRootFolder : Folder
{
- public override async Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
+ protected override async Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query)
{
if (query.Recursive)
{
@@ -37,6 +38,11 @@ namespace MediaBrowser.Controller.Entities
return PostFilterAndSort(result.Where(filter), query);
}
+ public override int GetChildCount(User user)
+ {
+ return GetChildren(user, true).Count();
+ }
+
[IgnoreDataMember]
protected override bool SupportsShortcutChildren
{
@@ -63,15 +69,6 @@ namespace MediaBrowser.Controller.Entities
return list;
}
- /// <summary>
- /// Get the children of this folder from the actual file system
- /// </summary>
- /// <returns>IEnumerable{BaseItem}.</returns>
- protected override IEnumerable<BaseItem> GetNonCachedChildren(IDirectoryService directoryService)
- {
- return base.GetNonCachedChildren(directoryService);
- }
-
public override bool BeforeMetadataRefresh()
{
var hasChanges = base.BeforeMetadataRefresh();
@@ -101,10 +98,5 @@ namespace MediaBrowser.Controller.Entities
LibraryManager.RegisterItem(item);
}
}
-
- public override void FillUserDataDtoValues(UserItemDataDto dto, UserItemData userData, User user)
- {
- // Nothing meaninful here and will only waste resources
- }
}
}
diff --git a/MediaBrowser.Controller/Entities/UserView.cs b/MediaBrowser.Controller/Entities/UserView.cs
index 41c19f11d..35375e7e6 100644
--- a/MediaBrowser.Controller/Entities/UserView.cs
+++ b/MediaBrowser.Controller/Entities/UserView.cs
@@ -45,7 +45,12 @@ namespace MediaBrowser.Controller.Entities
return list;
}
- public override Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
+ public override int GetChildCount(User user)
+ {
+ return GetChildren(user, true).Count();
+ }
+
+ protected override Task<QueryResult<BaseItem>> GetItemsInternal(InternalItemsQuery query)
{
var parent = this as Folder;
@@ -58,7 +63,7 @@ namespace MediaBrowser.Controller.Entities
parent = LibraryManager.GetItemById(ParentId) as Folder ?? parent;
}
- return new UserViewBuilder(UserViewManager, LiveTvManager, ChannelManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, CollectionManager, PlaylistManager)
+ return new UserViewBuilder(UserViewManager, LiveTvManager, ChannelManager, LibraryManager, Logger, UserDataManager, TVSeriesManager, ConfigurationManager, PlaylistManager)
.GetUserItems(parent, this, ViewType, query);
}
@@ -66,7 +71,8 @@ namespace MediaBrowser.Controller.Entities
{
var result = GetItems(new InternalItemsQuery
{
- User = user
+ User = user,
+ EnableTotalRecordCount = false
}).Result;
@@ -83,17 +89,19 @@ namespace MediaBrowser.Controller.Entities
return true;
}
- public override IEnumerable<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter)
+ public override IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query)
{
var result = GetItems(new InternalItemsQuery
{
User = user,
Recursive = true,
- Filter = filter
+ EnableTotalRecordCount = false,
+
+ ForceDirect = true
}).Result;
- return result.Items;
+ return result.Items.Where(i => UserViewBuilder.FilterItem(i, query));
}
protected override IEnumerable<BaseItem> GetEligibleChildrenForRecursiveChildren(User user)
diff --git a/MediaBrowser.Controller/Entities/UserViewBuilder.cs b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
index 2df2227bc..e2228bcaf 100644
--- a/MediaBrowser.Controller/Entities/UserViewBuilder.cs
+++ b/MediaBrowser.Controller/Entities/UserViewBuilder.cs
@@ -18,6 +18,9 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Model.Configuration;
+using MoreLinq;
namespace MediaBrowser.Controller.Entities
{
@@ -30,10 +33,10 @@ namespace MediaBrowser.Controller.Entities
private readonly ILogger _logger;
private readonly IUserDataManager _userDataManager;
private readonly ITVSeriesManager _tvSeriesManager;
- private readonly ICollectionManager _collectionManager;
+ private readonly IServerConfigurationManager _config;
private readonly IPlaylistManager _playlistManager;
- public UserViewBuilder(IUserViewManager userViewManager, ILiveTvManager liveTvManager, IChannelManager channelManager, ILibraryManager libraryManager, ILogger logger, IUserDataManager userDataManager, ITVSeriesManager tvSeriesManager, ICollectionManager collectionManager, 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;
@@ -42,7 +45,7 @@ namespace MediaBrowser.Controller.Entities
_logger = logger;
_userDataManager = userDataManager;
_tvSeriesManager = tvSeriesManager;
- _collectionManager = collectionManager;
+ _config = config;
_playlistManager = playlistManager;
}
@@ -125,13 +128,17 @@ namespace MediaBrowser.Controller.Entities
case CollectionType.HomeVideos:
case CollectionType.Games:
case CollectionType.MusicVideos:
- {
- if (query.Recursive)
{
- return GetResult(queryParent.GetRecursiveChildren(user, true), queryParent, query);
+ if (query.Recursive)
+ {
+ query.Recursive = true;
+ query.ParentId = queryParent.Id;
+ query.SetUser(user);
+
+ return _libraryManager.GetItemsResult(query);
+ }
+ return GetResult(queryParent.GetChildren(user, true), queryParent, query);
}
- return GetResult(queryParent.GetChildren(user, true), queryParent, query);
- }
case CollectionType.Folders:
return GetResult(user.RootFolder.GetChildren(user, true), queryParent, query);
@@ -140,7 +147,7 @@ namespace MediaBrowser.Controller.Entities
return await GetPlaylistsView(queryParent, user, query).ConfigureAwait(false);
case CollectionType.BoxSets:
- return await GetBoxsetView(queryParent, user, query).ConfigureAwait(false);
+ return GetBoxsetView(queryParent, user, query);
case CollectionType.TvShows:
return await GetTvView(queryParent, user, query).ConfigureAwait(false);
@@ -155,7 +162,7 @@ namespace MediaBrowser.Controller.Entities
return await GetTvGenres(queryParent, user, query).ConfigureAwait(false);
case SpecialFolder.TvGenre:
- return await GetTvGenreItems(queryParent, displayParent, user, query).ConfigureAwait(false);
+ return GetTvGenreItems(queryParent, displayParent, user, query);
case SpecialFolder.TvResume:
return GetTvResume(queryParent, user, query);
@@ -206,7 +213,7 @@ namespace MediaBrowser.Controller.Entities
return GetMusicLatest(queryParent, user, query);
case SpecialFolder.MusicPlaylists:
- return await GetMusicPlaylists(queryParent, user, query).ConfigureAwait(false);
+ return GetMusicPlaylists(queryParent, user, query);
case SpecialFolder.MusicAlbums:
return GetMusicAlbums(queryParent, user, query);
@@ -250,9 +257,15 @@ namespace MediaBrowser.Controller.Entities
{
if (query.Recursive)
{
- var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }, i => FilterItem(i, query));
+ query.Recursive = true;
+ query.SetUser(user);
- return PostFilterAndSort(items, parent, null, query);
+ 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>();
@@ -310,21 +323,26 @@ namespace MediaBrowser.Controller.Entities
private async Task<QueryResult<BaseItem>> GetMusicGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query)
{
- var items = GetRecursiveChildren(queryParent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
- .Where(i => !i.IsFolder)
- .Where(i => i.Genres.Contains(displayParent.Name, StringComparer.OrdinalIgnoreCase))
- .OfType<IHasAlbumArtist>();
+ query.Recursive = true;
+ query.ParentId = queryParent.Id;
+ query.Genres = new[] { displayParent.Name };
+ query.SetUser(user);
- var artists = _libraryManager.GetAlbumArtists(items);
+ query.IncludeItemTypes = new[] { typeof(MusicAlbum).Name };
- return GetResult(artists, queryParent, query);
+ return _libraryManager.GetItemsResult(query);
}
private QueryResult<BaseItem> GetMusicAlbumArtists(Folder parent, User user, InternalItemsQuery query)
{
- var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
- .Where(i => !i.IsFolder)
- .OfType<IHasAlbumArtist>();
+ var items = parent.QueryRecursive(new InternalItemsQuery(user)
+ {
+ Recursive = true,
+ ParentId = parent.Id,
+ IncludeItemTypes = new[] { typeof(Audio.Audio).Name },
+ EnableTotalRecordCount = false
+
+ }).Items.Cast<IHasAlbumArtist>();
var artists = _libraryManager.GetAlbumArtists(items);
@@ -333,9 +351,14 @@ namespace MediaBrowser.Controller.Entities
private QueryResult<BaseItem> GetMusicArtists(Folder parent, User user, InternalItemsQuery query)
{
- var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
- .Where(i => !i.IsFolder)
- .OfType<IHasArtist>();
+ var items = parent.QueryRecursive(new InternalItemsQuery(user)
+ {
+ Recursive = true,
+ ParentId = parent.Id,
+ IncludeItemTypes = new[] { typeof(Audio.Audio).Name, typeof(MusicVideo).Name },
+ EnableTotalRecordCount = false
+
+ }).Items.Cast<IHasArtist>();
var artists = _libraryManager.GetArtists(items);
@@ -344,35 +367,50 @@ namespace MediaBrowser.Controller.Entities
private QueryResult<BaseItem> GetFavoriteArtists(Folder parent, User user, InternalItemsQuery query)
{
- var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos })
- .Where(i => !i.IsFolder)
- .OfType<IHasAlbumArtist>();
+ var items = parent.QueryRecursive(new InternalItemsQuery(user)
+ {
+ Recursive = true,
+ ParentId = parent.Id,
+ IncludeItemTypes = new[] { typeof(Audio.Audio).Name },
+ EnableTotalRecordCount = false
- var artists = _libraryManager.GetAlbumArtists(items).Where(i => _userDataManager.GetUserData(user.Id, i.GetUserDataKey()).IsFavorite);
+ }).Items.Cast<IHasAlbumArtist>();
+
+ var artists = _libraryManager.GetAlbumArtists(items).Where(i => _userDataManager.GetUserData(user, i).IsFavorite);
return GetResult(artists, parent, query);
}
- private Task<QueryResult<BaseItem>> GetMusicPlaylists(Folder parent, User user, InternalItemsQuery query)
+ private QueryResult<BaseItem> GetMusicPlaylists(Folder parent, User user, InternalItemsQuery query)
{
- query.IncludeItemTypes = new[] { "Playlist" };
+ query.ParentId = null;
+ query.IncludeItemTypes = new[] { typeof(Playlist).Name };
+ query.SetUser(user);
query.Recursive = true;
- return parent.GetItems(query);
+ return _libraryManager.GetItemsResult(query);
}
private QueryResult<BaseItem> GetMusicAlbums(Folder parent, User user, InternalItemsQuery query)
{
- var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }, i => i is MusicAlbum && FilterItem(i, query));
+ query.Recursive = true;
+ query.ParentId = parent.Id;
+ query.SetUser(user);
- return PostFilterAndSort(items, parent, null, query);
+ query.IncludeItemTypes = new[] { typeof(MusicAlbum).Name };
+
+ return _libraryManager.GetItemsResult(query);
}
private QueryResult<BaseItem> GetMusicSongs(Folder parent, User user, InternalItemsQuery query)
{
- var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }, i => i is Audio.Audio && FilterItem(i, query));
+ query.Recursive = true;
+ query.ParentId = parent.Id;
+ query.SetUser(user);
- return PostFilterAndSort(items, parent, null, query);
+ query.IncludeItemTypes = new[] { typeof(Audio.Audio).Name };
+
+ return _libraryManager.GetItemsResult(query);
}
private QueryResult<BaseItem> GetMusicLatest(Folder parent, User user, InternalItemsQuery query)
@@ -389,27 +427,29 @@ namespace MediaBrowser.Controller.Entities
query.SortBy = new string[] { };
- //var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music, CollectionType.MusicVideos }, i => i is MusicVideo || i is Audio.Audio && FilterItem(i, query));
-
return PostFilterAndSort(items, parent, null, query);
}
private QueryResult<BaseItem> GetFavoriteSongs(Folder parent, User user, InternalItemsQuery query)
{
+ query.Recursive = true;
+ query.ParentId = parent.Id;
+ query.SetUser(user);
query.IsFavorite = true;
+ query.IncludeItemTypes = new[] { typeof(Audio.Audio).Name };
- var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music }, i => i is Audio.Audio && FilterItem(i, query));
-
- return PostFilterAndSort(items, parent, null, query);
+ return _libraryManager.GetItemsResult(query);
}
private QueryResult<BaseItem> GetFavoriteAlbums(Folder parent, User user, InternalItemsQuery query)
{
+ query.Recursive = true;
+ query.ParentId = parent.Id;
+ query.SetUser(user);
query.IsFavorite = true;
+ query.IncludeItemTypes = new[] { typeof(MusicAlbum).Name };
- var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Music }, i => i is MusicAlbum && FilterItem(i, query));
-
- return PostFilterAndSort(items, parent, null, query);
+ return _libraryManager.GetItemsResult(query);
}
private async Task<QueryResult<BaseItem>> FindPlaylists(Folder parent, User user, InternalItemsQuery query)
@@ -428,19 +468,15 @@ namespace MediaBrowser.Controller.Entities
{
if (query.Recursive)
{
- var recursiveItems = GetRecursiveChildren(parent, user,
- new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty })
- .Where(i => i is Movie || i is BoxSet);
+ query.Recursive = true;
+ query.SetUser(user);
- //var collections = _collectionManager.CollapseItemsWithinBoxSets(recursiveItems, user).ToList();
-
- //if (collections.Count > 0)
- //{
- // recursiveItems.AddRange(_collectionManager.CollapseItemsWithinBoxSets(recursiveItems, user));
- // recursiveItems = recursiveItems.DistinctBy(i => i.Id).ToList();
- //}
+ if (query.IncludeItemTypes.Length == 0)
+ {
+ query.IncludeItemTypes = new[] { typeof(Movie).Name, typeof(BoxSet).Name };
+ }
- return GetResult(recursiveItems, parent, query);
+ return parent.QueryRecursive(query);
}
var list = new List<BaseItem>();
@@ -457,43 +493,51 @@ namespace MediaBrowser.Controller.Entities
private QueryResult<BaseItem> GetFavoriteMovies(Folder parent, User user, InternalItemsQuery query)
{
+ query.Recursive = true;
+ query.ParentId = parent.Id;
+ query.SetUser(user);
query.IsFavorite = true;
+ query.IncludeItemTypes = new[] { typeof(Movie).Name };
- var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }, i => i is Movie && FilterItem(i, query));
-
- return PostFilterAndSort(items, parent, null, query);
+ return _libraryManager.GetItemsResult(query);
}
private QueryResult<BaseItem> GetFavoriteSeries(Folder parent, User user, InternalItemsQuery query)
{
+ query.Recursive = true;
+ query.ParentId = parent.Id;
+ query.SetUser(user);
query.IsFavorite = true;
+ query.IncludeItemTypes = new[] { typeof(Series).Name };
- var items = GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }, i => i is Series && FilterItem(i, query));
-
- return PostFilterAndSort(items, parent, null, query);
+ return _libraryManager.GetItemsResult(query);
}
private QueryResult<BaseItem> GetFavoriteEpisodes(Folder parent, User user, InternalItemsQuery query)
{
+ query.Recursive = true;
+ query.ParentId = parent.Id;
+ query.SetUser(user);
query.IsFavorite = true;
+ query.IncludeItemTypes = new[] { typeof(Episode).Name };
- var items = GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }, i => i is Episode && FilterItem(i, query));
-
- return PostFilterAndSort(items, parent, null, query);
+ return _libraryManager.GetItemsResult(query);
}
private QueryResult<BaseItem> GetMovieMovies(Folder parent, User user, InternalItemsQuery query)
{
- var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }, i => i is Movie && FilterItem(i, query));
+ query.Recursive = true;
+ query.ParentId = parent.Id;
+ query.SetUser(user);
- return PostFilterAndSort(items, parent, null, query);
+ query.IncludeItemTypes = new[] { typeof(Movie).Name };
+
+ return _libraryManager.GetItemsResult(query);
}
private QueryResult<BaseItem> GetMovieCollections(Folder parent, User user, InternalItemsQuery query)
{
- var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }, i => i is BoxSet && FilterItem(i, query));
-
- return PostFilterAndSort(items, parent, null, query);
+ return GetBoxsetView(parent, user, query);
}
private QueryResult<BaseItem> GetMovieLatest(Folder parent, User user, InternalItemsQuery query)
@@ -501,9 +545,13 @@ namespace MediaBrowser.Controller.Entities
query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName };
query.SortOrder = SortOrder.Descending;
- var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }, i => i is Movie && FilterItem(i, query));
+ query.Recursive = true;
+ query.ParentId = parent.Id;
+ query.SetUser(user);
+ query.Limit = GetSpecialItemsLimit();
+ query.IncludeItemTypes = new[] { typeof(Movie).Name };
- return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query);
+ return ConvertToResult(_libraryManager.GetItemList(query));
}
private QueryResult<BaseItem> GetMovieResume(Folder parent, User user, InternalItemsQuery query)
@@ -511,16 +559,34 @@ namespace MediaBrowser.Controller.Entities
query.SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName };
query.SortOrder = SortOrder.Descending;
query.IsResumable = true;
+ query.Recursive = true;
+ query.ParentId = parent.Id;
+ query.SetUser(user);
+ query.Limit = GetSpecialItemsLimit();
+ query.IncludeItemTypes = new[] { typeof(Movie).Name };
- var items = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty }, i => i is Movie && FilterItem(i, query));
+ return ConvertToResult(_libraryManager.GetItemList(query));
+ }
- return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query);
+ private QueryResult<BaseItem> ConvertToResult(IEnumerable<BaseItem> items)
+ {
+ var arr = items.ToArray();
+ return new QueryResult<BaseItem>
+ {
+ Items = arr,
+ TotalRecordCount = arr.Length
+ };
}
private async Task<QueryResult<BaseItem>> GetMovieGenres(Folder parent, User user, InternalItemsQuery query)
{
- var tasks = GetRecursiveChildren(parent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty })
- .Where(i => i is Movie)
+ var tasks = parent.QueryRecursive(new InternalItemsQuery(user)
+ {
+ IncludeItemTypes = new[] { typeof(Movie).Name },
+ Recursive = true,
+ EnableTotalRecordCount = false
+
+ }).Items
.SelectMany(i => i.Genres)
.DistinctNames()
.Select(i =>
@@ -547,11 +613,14 @@ namespace MediaBrowser.Controller.Entities
private async Task<QueryResult<BaseItem>> GetMovieGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query)
{
- var items = GetRecursiveChildren(queryParent, user, new[] { CollectionType.Movies, CollectionType.BoxSets, string.Empty })
- .Where(i => i is Movie)
- .Where(i => i.Genres.Contains(displayParent.Name, StringComparer.OrdinalIgnoreCase));
+ query.Recursive = true;
+ query.ParentId = queryParent.Id;
+ query.Genres = new[] { displayParent.Name };
+ query.SetUser(user);
+
+ query.IncludeItemTypes = new[] { typeof(Movie).Name };
- return GetResult(items, queryParent, query);
+ return _libraryManager.GetItemsResult(query);
}
private async Task<QueryResult<BaseItem>> GetPlaylistsView(Folder parent, User user, InternalItemsQuery query)
@@ -559,20 +628,29 @@ namespace MediaBrowser.Controller.Entities
return GetResult(_playlistManager.GetPlaylists(user.Id.ToString("N")), parent, query);
}
- private async Task<QueryResult<BaseItem>> GetBoxsetView(Folder parent, User user, InternalItemsQuery query)
+ private QueryResult<BaseItem> GetBoxsetView(Folder parent, User user, InternalItemsQuery query)
{
- var collections = _collectionManager.GetCollections(user);
+ query.ParentId = null;
+ query.IncludeItemTypes = new[] { typeof(BoxSet).Name };
+ query.SetUser(user);
+ query.Recursive = true;
- return GetResult(collections, parent, query);
+ return _libraryManager.GetItemsResult(query);
}
private async Task<QueryResult<BaseItem>> GetTvView(Folder parent, User user, InternalItemsQuery query)
{
if (query.Recursive)
{
- var items = GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }, i => (i is Series || i is Season || i is Episode) && FilterItem(i, query));
+ query.Recursive = true;
+ query.SetUser(user);
+
+ if (query.IncludeItemTypes.Length == 0)
+ {
+ query.IncludeItemTypes = new[] { typeof(Series).Name, typeof(Season).Name, typeof(Episode).Name };
+ }
- return PostFilterAndSort(items, parent, null, query);
+ return parent.QueryRecursive(query);
}
var list = new List<BaseItem>();
@@ -593,9 +671,14 @@ namespace MediaBrowser.Controller.Entities
query.SortBy = new[] { ItemSortBy.DateCreated, ItemSortBy.SortName };
query.SortOrder = SortOrder.Descending;
- var items = GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }, i => i is Episode && FilterItem(i, query));
+ query.Recursive = true;
+ query.ParentId = parent.Id;
+ query.SetUser(user);
+ query.Limit = GetSpecialItemsLimit();
+ query.IncludeItemTypes = new[] { typeof(Episode).Name };
+ query.ExcludeLocationTypes = new[] { LocationType.Virtual };
- return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query);
+ return ConvertToResult(_libraryManager.GetItemList(query));
}
private QueryResult<BaseItem> GetTvNextUp(Folder parent, InternalItemsQuery query)
@@ -618,23 +701,35 @@ namespace MediaBrowser.Controller.Entities
query.SortBy = new[] { ItemSortBy.DatePlayed, ItemSortBy.SortName };
query.SortOrder = SortOrder.Descending;
query.IsResumable = true;
+ query.Recursive = true;
+ query.ParentId = parent.Id;
+ query.SetUser(user);
+ query.Limit = GetSpecialItemsLimit();
+ query.IncludeItemTypes = new[] { typeof(Episode).Name };
- var items = GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }, i => i is Episode && FilterItem(i, query));
-
- return PostFilterAndSort(items, parent, GetSpecialItemsLimit(), query);
+ return ConvertToResult(_libraryManager.GetItemList(query));
}
private QueryResult<BaseItem> GetTvSeries(Folder parent, User user, InternalItemsQuery query)
{
- var items = GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty }, i => i is Series && FilterItem(i, query));
+ query.Recursive = true;
+ query.ParentId = parent.Id;
+ query.SetUser(user);
- return PostFilterAndSort(items, parent, null, query);
+ query.IncludeItemTypes = new[] { typeof(Series).Name };
+
+ return _libraryManager.GetItemsResult(query);
}
private async Task<QueryResult<BaseItem>> GetTvGenres(Folder parent, User user, InternalItemsQuery query)
{
- var tasks = GetRecursiveChildren(parent, user, new[] { CollectionType.TvShows, string.Empty })
- .OfType<Series>()
+ var tasks = parent.QueryRecursive(new InternalItemsQuery(user)
+ {
+ IncludeItemTypes = new[] { typeof(Series).Name },
+ Recursive = true,
+ EnableTotalRecordCount = false
+
+ }).Items
.SelectMany(i => i.Genres)
.DistinctNames()
.Select(i =>
@@ -659,13 +754,16 @@ namespace MediaBrowser.Controller.Entities
return GetResult(genres, parent, query);
}
- private async Task<QueryResult<BaseItem>> GetTvGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query)
+ private QueryResult<BaseItem> GetTvGenreItems(Folder queryParent, Folder displayParent, User user, InternalItemsQuery query)
{
- var items = GetRecursiveChildren(queryParent, user, new[] { CollectionType.TvShows, string.Empty })
- .Where(i => i is Series)
- .Where(i => i.Genres.Contains(displayParent.Name, StringComparer.OrdinalIgnoreCase));
+ query.Recursive = true;
+ query.ParentId = queryParent.Id;
+ query.Genres = new[] { displayParent.Name };
+ query.SetUser(user);
- return GetResult(items, queryParent, query);
+ query.IncludeItemTypes = new[] { typeof(Series).Name };
+
+ return _libraryManager.GetItemsResult(query);
}
private QueryResult<BaseItem> GetResult<T>(QueryResult<T> result)
@@ -685,12 +783,12 @@ namespace MediaBrowser.Controller.Entities
{
items = items.Where(i => Filter(i, query.User, query, _userDataManager, _libraryManager));
- return PostFilterAndSort(items, queryParent, null, query, _libraryManager);
+ return PostFilterAndSort(items, queryParent, null, query, _libraryManager, _config);
}
- public bool FilterItem(BaseItem item, InternalItemsQuery query)
+ public static bool FilterItem(BaseItem item, InternalItemsQuery query)
{
- return Filter(item, query.User, query, _userDataManager, _libraryManager);
+ return Filter(item, query.User, query, BaseItem.UserDataManager, BaseItem.LibraryManager);
}
private QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items,
@@ -698,14 +796,15 @@ namespace MediaBrowser.Controller.Entities
int? totalRecordLimit,
InternalItemsQuery query)
{
- return PostFilterAndSort(items, queryParent, totalRecordLimit, query, _libraryManager);
+ return PostFilterAndSort(items, queryParent, totalRecordLimit, query, _libraryManager, _config);
}
public static QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items,
BaseItem queryParent,
int? totalRecordLimit,
InternalItemsQuery query,
- ILibraryManager libraryManager)
+ ILibraryManager libraryManager,
+ IServerConfigurationManager configurationManager)
{
var user = query.User;
@@ -714,7 +813,7 @@ namespace MediaBrowser.Controller.Entities
query.IsVirtualUnaired,
query.IsUnaired);
- items = CollapseBoxSetItemsIfNeeded(items, query, queryParent, user);
+ items = CollapseBoxSetItemsIfNeeded(items, query, queryParent, user, configurationManager);
// This must be the last filter
if (!string.IsNullOrEmpty(query.AdjacentTo))
@@ -728,14 +827,15 @@ namespace MediaBrowser.Controller.Entities
public static IEnumerable<BaseItem> CollapseBoxSetItemsIfNeeded(IEnumerable<BaseItem> items,
InternalItemsQuery query,
BaseItem queryParent,
- User user)
+ User user,
+ IServerConfigurationManager configurationManager)
{
if (items == null)
{
throw new ArgumentNullException("items");
}
- if (CollapseBoxSetItems(query, queryParent, user))
+ if (CollapseBoxSetItems(query, queryParent, user, configurationManager))
{
items = BaseItem.CollectionManager.CollapseItemsWithinBoxSets(items, user);
}
@@ -768,7 +868,8 @@ namespace MediaBrowser.Controller.Entities
public static bool CollapseBoxSetItems(InternalItemsQuery query,
BaseItem queryParent,
- User user)
+ User user,
+ IServerConfigurationManager configurationManager)
{
// Could end up stuck in a loop like this
if (queryParent is BoxSet)
@@ -780,12 +881,12 @@ namespace MediaBrowser.Controller.Entities
if (!param.HasValue)
{
- if (user != null && !user.Configuration.GroupMoviesIntoBoxSets)
+ if (user != null && !configurationManager.Configuration.EnableGroupingIntoCollections)
{
return false;
}
- if (query.IncludeItemTypes.Contains("Movie", StringComparer.OrdinalIgnoreCase))
+ if (query.IncludeItemTypes.Length == 0 || query.IncludeItemTypes.Contains("Movie", StringComparer.OrdinalIgnoreCase))
{
param = true;
}
@@ -911,11 +1012,6 @@ namespace MediaBrowser.Controller.Entities
return false;
}
- if (request.IsYearMismatched.HasValue)
- {
- return false;
- }
-
if (!string.IsNullOrWhiteSpace(request.Person))
{
return false;
@@ -1053,22 +1149,6 @@ namespace MediaBrowser.Controller.Entities
bool? isVirtualUnaired,
bool? isUnaired)
{
- if (isMissing.HasValue && isVirtualUnaired.HasValue)
- {
- if (!isMissing.Value && !isVirtualUnaired.Value)
- {
- return items.Where(i =>
- {
- var e = i as Season;
- if (e != null)
- {
- return !e.IsMissingOrVirtualUnaired;
- }
- return true;
- });
- }
- }
-
if (isMissing.HasValue)
{
var val = isMissing.Value;
@@ -1077,7 +1157,7 @@ namespace MediaBrowser.Controller.Entities
var e = i as Season;
if (e != null)
{
- return e.IsMissingSeason == val;
+ return (e.IsMissingSeason) == val;
}
return true;
});
@@ -1121,7 +1201,7 @@ namespace MediaBrowser.Controller.Entities
{
var user = query.User;
- items = libraryManager.ReplaceVideosWithPrimaryVersions(items);
+ items = items.DistinctBy(i => i.PresentationUniqueKey, StringComparer.OrdinalIgnoreCase);
if (query.SortBy.Length > 0)
{
@@ -1209,16 +1289,11 @@ namespace MediaBrowser.Controller.Entities
return false;
}
- if (query.Filter != null && !query.Filter(item))
- {
- return false;
- }
-
UserItemData userData = null;
if (query.IsLiked.HasValue)
{
- userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey());
+ userData = userData ?? userDataManager.GetUserData(user, item);
if (!userData.Likes.HasValue || userData.Likes != query.IsLiked.Value)
{
@@ -1228,7 +1303,7 @@ namespace MediaBrowser.Controller.Entities
if (query.IsFavoriteOrLiked.HasValue)
{
- userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey());
+ userData = userData ?? userDataManager.GetUserData(user, item);
var isFavoriteOrLiked = userData.IsFavorite || (userData.Likes ?? false);
if (isFavoriteOrLiked != query.IsFavoriteOrLiked.Value)
@@ -1239,7 +1314,7 @@ namespace MediaBrowser.Controller.Entities
if (query.IsFavorite.HasValue)
{
- userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey());
+ userData = userData ?? userDataManager.GetUserData(user, item);
if (userData.IsFavorite != query.IsFavorite.Value)
{
@@ -1249,7 +1324,7 @@ namespace MediaBrowser.Controller.Entities
if (query.IsResumable.HasValue)
{
- userData = userData ?? userDataManager.GetUserData(user.Id, item.GetUserDataKey());
+ userData = userData ?? userDataManager.GetUserData(user, item);
var isResumable = userData.PlaybackPositionTicks > 0;
if (isResumable != query.IsResumable.Value)
@@ -1355,16 +1430,6 @@ namespace MediaBrowser.Controller.Entities
}
}
- if (query.IsYearMismatched.HasValue)
- {
- var filterValue = query.IsYearMismatched.Value;
-
- if (IsYearMismatched(item, libraryManager) != filterValue)
- {
- return false;
- }
- }
-
if (query.HasOfficialRating.HasValue)
{
var filterValue = query.HasOfficialRating.Value;
@@ -1598,12 +1663,7 @@ namespace MediaBrowser.Controller.Entities
var tags = query.Tags;
if (tags.Length > 0)
{
- var hasTags = item as IHasTags;
- if (hasTags == null)
- {
- return false;
- }
- if (!tags.Any(v => hasTags.Tags.Contains(v, StringComparer.OrdinalIgnoreCase)))
+ if (!tags.Any(v => item.Tags.Contains(v, StringComparer.OrdinalIgnoreCase)))
{
return false;
}
@@ -1735,7 +1795,7 @@ namespace MediaBrowser.Controller.Entities
if (query.SeriesStatuses.Length > 0)
{
- var ok = new[] { item }.OfType<Series>().Any(p => p.Status.HasValue && query.SeriesStatuses.Contains(p.Status.Value));
+ var ok = new[] { item }.OfType<Series>().Any(p => p.Status.HasValue && query.SeriesStatuses.Contains(p.Status.Value));
if (!ok)
{
return false;
@@ -1884,26 +1944,6 @@ namespace MediaBrowser.Controller.Entities
return parent.GetRecursiveChildren(user);
}
- private IEnumerable<BaseItem> GetRecursiveChildren(Folder parent, User user, IEnumerable<string> viewTypes, Func<BaseItem, bool> filter)
- {
- if (parent == null || parent is UserView)
- {
- if (user == null)
- {
- return GetMediaFolders(null, viewTypes).SelectMany(i => i.GetRecursiveChildren(filter));
- }
-
- return GetMediaFolders(user, viewTypes).SelectMany(i => i.GetRecursiveChildren(user, filter));
- }
-
- if (user == null)
- {
- return parent.GetRecursiveChildren(filter);
- }
-
- return parent.GetRecursiveChildren(user, filter);
- }
-
private async Task<QueryResult<BaseItem>> GetLiveTvView(Folder queryParent, User user, InternalItemsQuery query)
{
if (query.Recursive)
@@ -1936,34 +1976,6 @@ namespace MediaBrowser.Controller.Entities
return _userViewManager.GetUserSubView(parent.Id.ToString("N"), type, sortName, CancellationToken.None);
}
- public static bool IsYearMismatched(BaseItem item, ILibraryManager libraryManager)
- {
- if (item.ProductionYear.HasValue)
- {
- var path = item.Path;
-
- if (!string.IsNullOrEmpty(path))
- {
- var info = libraryManager.ParseName(Path.GetFileName(path));
- var yearInName = info.Year;
-
- // Go up a level if we didn't get a year
- if (!yearInName.HasValue)
- {
- info = libraryManager.ParseName(Path.GetFileName(Path.GetDirectoryName(path)));
- yearInName = info.Year;
- }
-
- if (yearInName.HasValue)
- {
- return yearInName.Value != item.ProductionYear.Value;
- }
- }
- }
-
- return false;
- }
-
public static IEnumerable<BaseItem> FilterForAdjacency(IEnumerable<BaseItem> items, string adjacentToId)
{
var list = items.ToList();
diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs
index 511606efc..eba1e466a 100644
--- a/MediaBrowser.Controller/Entities/Video.cs
+++ b/MediaBrowser.Controller/Entities/Video.cs
@@ -21,14 +21,14 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class Video : BaseItem,
IHasAspectRatio,
- IHasTags,
ISupportsPlaceHolders,
IHasMediaSources,
IHasShortOverview,
IThemeMedia,
IArchivable
{
- public Guid? PrimaryVersionId { get; set; }
+ [IgnoreDataMember]
+ public string PrimaryVersionId { get; set; }
public List<string> AdditionalParts { get; set; }
public List<string> LocalAlternateVersions { get; set; }
@@ -44,10 +44,27 @@ namespace MediaBrowser.Controller.Entities
}
}
- public long? Size { get; set; }
- public string Container { get; set; }
+ [IgnoreDataMember]
+ public override string PresentationUniqueKey
+ {
+ get
+ {
+ if (!string.IsNullOrWhiteSpace(PrimaryVersionId))
+ {
+ return PrimaryVersionId;
+ }
+
+ return base.PresentationUniqueKey;
+ }
+ }
+
+ [IgnoreDataMember]
+ public override bool EnableForceSaveOnDateModifiedChange
+ {
+ get { return true; }
+ }
+
public int? TotalBitrate { get; set; }
- public string ShortOverview { get; set; }
public ExtraType? ExtraType { get; set; }
/// <summary>
@@ -56,6 +73,72 @@ namespace MediaBrowser.Controller.Entities
/// <value>The timestamp.</value>
public TransportStreamTimestamp? Timestamp { get; set; }
+ /// <summary>
+ /// Gets or sets the subtitle paths.
+ /// </summary>
+ /// <value>The subtitle paths.</value>
+ public List<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 video bit rate.
+ /// </summary>
+ /// <value>The video bit rate.</value>
+ public int? VideoBitRate { 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; }
+
+ /// <summary>
+ /// If the video is a folder-rip, this will hold the file list for the largest playlist
+ /// </summary>
+ public List<string> PlayableStreamFileNames { get; set; }
+
+ /// <summary>
+ /// Gets the playable stream files.
+ /// </summary>
+ /// <returns>List{System.String}.</returns>
+ public List<string> GetPlayableStreamFiles()
+ {
+ return GetPlayableStreamFiles(Path);
+ }
+
+ /// <summary>
+ /// Gets or sets the aspect ratio.
+ /// </summary>
+ /// <value>The aspect ratio.</value>
+ public string AspectRatio { get; set; }
+
public Video()
{
PlayableStreamFileNames = new List<string>();
@@ -80,23 +163,6 @@ namespace MediaBrowser.Controller.Entities
}
[IgnoreDataMember]
- public override LocationType LocationType
- {
- get
- {
- if (SourceType == SourceType.Channel)
- {
- if (string.IsNullOrEmpty(Path))
- {
- return LocationType.Remote;
- }
- }
-
- return base.LocationType;
- }
- }
-
- [IgnoreDataMember]
public override bool SupportsAddingToPlaylist
{
get { return LocationType == LocationType.FileSystem && RunTimeTicks.HasValue; }
@@ -107,6 +173,14 @@ namespace MediaBrowser.Controller.Entities
{
get
{
+ if (!string.IsNullOrWhiteSpace(PrimaryVersionId))
+ {
+ var item = LibraryManager.GetItemById(PrimaryVersionId) as Video;
+ if (item != null)
+ {
+ return item.MediaSourceCount;
+ }
+ }
return LinkedAlternateVersions.Count + LocalAlternateVersions.Count + 1;
}
}
@@ -148,42 +222,65 @@ namespace MediaBrowser.Controller.Entities
return LocalAlternateVersions.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
}
- protected override string CreateUserDataKey()
+ [IgnoreDataMember]
+ protected virtual bool EnableDefaultVideoUserDataKeys
{
- if (ExtraType.HasValue)
+ get
{
- var key = this.GetProviderId(MetadataProviders.Imdb) ?? this.GetProviderId(MetadataProviders.Tmdb);
+ return true;
+ }
+ }
+
+ public override List<string> GetUserDataKeys()
+ {
+ var list = base.GetUserDataKeys();
- if (!string.IsNullOrWhiteSpace(key))
+ if (EnableDefaultVideoUserDataKeys)
+ {
+ if (ExtraType.HasValue)
{
- key = key + "-" + ExtraType.ToString().ToLower();
+ var key = this.GetProviderId(MetadataProviders.Tmdb);
+ if (!string.IsNullOrWhiteSpace(key))
+ {
+ list.Insert(0, GetUserDataKey(key));
+ }
- // Make sure different trailers have their own data.
- if (RunTimeTicks.HasValue)
+ key = this.GetProviderId(MetadataProviders.Imdb);
+ if (!string.IsNullOrWhiteSpace(key))
{
- key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture);
+ list.Insert(0, GetUserDataKey(key));
+ }
+ }
+ else
+ {
+ var key = this.GetProviderId(MetadataProviders.Imdb);
+ if (!string.IsNullOrWhiteSpace(key))
+ {
+ list.Insert(0, key);
}
- return key;
+ key = this.GetProviderId(MetadataProviders.Tmdb);
+ if (!string.IsNullOrWhiteSpace(key))
+ {
+ list.Insert(0, key);
+ }
}
}
- return base.CreateUserDataKey();
+ return list;
}
- /// <summary>
- /// Gets the linked children.
- /// </summary>
- /// <returns>IEnumerable{BaseItem}.</returns>
- public IEnumerable<Video> GetAlternateVersions()
+ private string GetUserDataKey(string providerId)
{
- var filesWithinSameDirectory = GetLocalAlternateVersionIds()
- .Select(i => LibraryManager.GetItemById(i))
- .Where(i => i != null)
- .OfType<Video>();
+ var key = providerId + "-" + ExtraType.ToString().ToLower();
- return filesWithinSameDirectory.Concat(GetLinkedAlternateVersions())
- .OrderBy(i => i.SortName);
+ // Make sure different trailers have their own data.
+ if (RunTimeTicks.HasValue)
+ {
+ key += "-" + RunTimeTicks.Value.ToString(CultureInfo.InvariantCulture);
+ }
+
+ return key;
}
public IEnumerable<Video> GetLinkedAlternateVersions()
@@ -210,72 +307,6 @@ namespace MediaBrowser.Controller.Entities
.OrderBy(i => i.SortName);
}
- /// <summary>
- /// Gets or sets the subtitle paths.
- /// </summary>
- /// <value>The subtitle paths.</value>
- public List<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 video bit rate.
- /// </summary>
- /// <value>The video bit rate.</value>
- public int? VideoBitRate { 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; }
-
- /// <summary>
- /// If the video is a folder-rip, this will hold the file list for the largest playlist
- /// </summary>
- public List<string> PlayableStreamFileNames { get; set; }
-
- /// <summary>
- /// Gets the playable stream files.
- /// </summary>
- /// <returns>List{System.String}.</returns>
- public List<string> GetPlayableStreamFiles()
- {
- return GetPlayableStreamFiles(Path);
- }
-
- /// <summary>
- /// Gets or sets the aspect ratio.
- /// </summary>
- /// <value>The aspect ratio.</value>
- public string AspectRatio { get; set; }
-
[IgnoreDataMember]
public override string ContainingFolderPath
{
@@ -334,6 +365,11 @@ namespace MediaBrowser.Controller.Entities
{
return false;
}
+
+ if (newAsVideo.VideoType != VideoType)
+ {
+ return false;
+ }
}
return base.IsValidFromResolver(newItem);
@@ -480,6 +516,36 @@ namespace MediaBrowser.Controller.Entities
}).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 IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
{
if (SourceType == SourceType.Channel)
@@ -498,13 +564,8 @@ namespace MediaBrowser.Controller.Entities
};
}
- var item = this;
-
- var result = item.GetAlternateVersions()
- .Select(i => GetVersionInfo(enablePathSubstitution, i, MediaSourceType.Grouping))
- .ToList();
-
- result.Add(GetVersionInfo(enablePathSubstitution, item, MediaSourceType.Default));
+ var list = GetAllVideosForMediaSources();
+ var result = list.Select(i => GetVersionInfo(enablePathSubstitution, i.Item1, i.Item2)).ToList();
return result.OrderBy(i =>
{
diff --git a/MediaBrowser.Controller/Entities/Year.cs b/MediaBrowser.Controller/Entities/Year.cs
index 163dcd667..db896f1fc 100644
--- a/MediaBrowser.Controller/Entities/Year.cs
+++ b/MediaBrowser.Controller/Entities/Year.cs
@@ -11,13 +11,12 @@ namespace MediaBrowser.Controller.Entities
/// </summary>
public class Year : BaseItem, IItemByName
{
- /// <summary>
- /// Gets the user data key.
- /// </summary>
- /// <returns>System.String.</returns>
- protected override string CreateUserDataKey()
+ public override List<string> GetUserDataKeys()
{
- return "Year-" + Name;
+ var list = base.GetUserDataKeys();
+
+ list.Insert(0, "Year-" + Name);
+ return list;
}
/// <summary>
@@ -71,6 +70,22 @@ namespace MediaBrowser.Controller.Entities
return inputItems.Where(i => i.ProductionYear.HasValue && i.ProductionYear.Value == year);
}
+ 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;
diff --git a/MediaBrowser.Controller/Health/IHealthMonitor.cs b/MediaBrowser.Controller/Health/IHealthMonitor.cs
new file mode 100644
index 000000000..b8ad98fc1
--- /dev/null
+++ b/MediaBrowser.Controller/Health/IHealthMonitor.cs
@@ -0,0 +1,12 @@
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Model.Notifications;
+
+namespace MediaBrowser.Controller.Health
+{
+ public interface IHealthMonitor
+ {
+ Task<List<Notification>> GetNotifications(CancellationToken cancellationToken);
+ }
+}
diff --git a/MediaBrowser.Controller/IServerApplicationHost.cs b/MediaBrowser.Controller/IServerApplicationHost.cs
index e4eecec18..f4c0e7658 100644
--- a/MediaBrowser.Controller/IServerApplicationHost.cs
+++ b/MediaBrowser.Controller/IServerApplicationHost.cs
@@ -3,6 +3,7 @@ using MediaBrowser.Model.System;
using System;
using System.Collections.Generic;
using System.Net;
+using System.Threading.Tasks;
namespace MediaBrowser.Controller
{
@@ -12,12 +13,12 @@ namespace MediaBrowser.Controller
public interface IServerApplicationHost : IApplicationHost
{
event EventHandler HasUpdateAvailableChanged;
-
+
/// <summary>
/// Gets the system info.
/// </summary>
/// <returns>SystemInfo.</returns>
- SystemInfo GetSystemInfo();
+ Task<SystemInfo> GetSystemInfo();
/// <summary>
/// Gets a value indicating whether [supports automatic run at startup].
@@ -65,13 +66,13 @@ namespace MediaBrowser.Controller
/// Gets the local ip address.
/// </summary>
/// <value>The local ip address.</value>
- List<IPAddress> LocalIpAddresses { get; }
+ Task<List<IPAddress>> GetLocalIpAddresses();
/// <summary>
/// Gets the local API URL.
/// </summary>
/// <value>The local API URL.</value>
- string LocalApiUrl { get; }
+ Task<string> GetLocalApiUrl();
/// <summary>
/// Gets the local API URL.
@@ -86,5 +87,7 @@ namespace MediaBrowser.Controller
/// <param name="ipAddress">The ip address.</param>
/// <returns>System.String.</returns>
string GetLocalApiUrl(IPAddress ipAddress);
+
+ void LaunchUrl(string url);
}
}
diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs
index c8b3d5131..ad38b9ea5 100644
--- a/MediaBrowser.Controller/Library/ILibraryManager.cs
+++ b/MediaBrowser.Controller/Library/ILibraryManager.cs
@@ -11,6 +11,7 @@ using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using CommonIO;
+using MediaBrowser.Model.Dto;
namespace MediaBrowser.Controller.Library
{
@@ -25,7 +26,7 @@ namespace MediaBrowser.Controller.Library
/// <param name="fileInfo">The file information.</param>
/// <param name="parent">The parent.</param>
/// <returns>BaseItem.</returns>
- BaseItem ResolvePath(FileSystemMetadata fileInfo,
+ BaseItem ResolvePath(FileSystemMetadata fileInfo,
Folder parent = null);
/// <summary>
@@ -36,9 +37,9 @@ namespace MediaBrowser.Controller.Library
/// <param name="parent">The parent.</param>
/// <param name="collectionType">Type of the collection.</param>
/// <returns>List{``0}.</returns>
- IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files,
+ IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files,
IDirectoryService directoryService,
- Folder parent, string
+ Folder parent, string
collectionType = null);
/// <summary>
@@ -59,8 +60,8 @@ namespace MediaBrowser.Controller.Library
/// </summary>
/// <param name="path">The path.</param>
/// <returns>BaseItem.</returns>
- BaseItem FindByPath(string path);
-
+ BaseItem FindByPath(string path, bool? isFolder);
+
/// <summary>
/// Gets the artist.
/// </summary>
@@ -151,13 +152,6 @@ namespace MediaBrowser.Controller.Library
BaseItem GetItemById(Guid id);
/// <summary>
- /// Gets the memory item by identifier.
- /// </summary>
- /// <param name="id">The identifier.</param>
- /// <returns>BaseItem.</returns>
- BaseItem GetMemoryItemById(Guid id);
-
- /// <summary>
/// Gets the intros.
/// </summary>
/// <param name="item">The item.</param>
@@ -243,6 +237,8 @@ namespace MediaBrowser.Controller.Library
/// <returns>BaseItem.</returns>
BaseItem RetrieveItem(Guid id);
+ bool IsScanRunning { get; }
+
/// <summary>
/// Occurs when [item added].
/// </summary>
@@ -290,7 +286,7 @@ namespace MediaBrowser.Controller.Library
/// <param name="path">The path.</param>
/// <returns>System.String.</returns>
string GetConfiguredContentType(string path);
-
+
/// <summary>
/// Normalizes the root path list.
/// </summary>
@@ -313,13 +309,6 @@ namespace MediaBrowser.Controller.Library
Task DeleteItem(BaseItem item, DeleteOptions options);
/// <summary>
- /// Replaces the videos with primary versions.
- /// </summary>
- /// <param name="items">The items.</param>
- /// <returns>IEnumerable{BaseItem}.</returns>
- IEnumerable<BaseItem> ReplaceVideosWithPrimaryVersions(IEnumerable<BaseItem> items);
-
- /// <summary>
/// Gets the named view.
/// </summary>
/// <param name="user">The user.</param>
@@ -332,8 +321,8 @@ namespace MediaBrowser.Controller.Library
Task<UserView> GetNamedView(User user,
string name,
string parentId,
- string viewType,
- string sortName,
+ string viewType,
+ string sortName,
CancellationToken cancellationToken);
/// <summary>
@@ -346,8 +335,8 @@ namespace MediaBrowser.Controller.Library
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task&lt;UserView&gt;.</returns>
Task<UserView> GetNamedView(User user,
- string name,
- string viewType,
+ string name,
+ string viewType,
string sortName,
CancellationToken cancellationToken);
@@ -393,7 +382,7 @@ namespace MediaBrowser.Controller.Library
string viewType,
string sortName,
CancellationToken cancellationToken);
-
+
/// <summary>
/// Determines whether [is video file] [the specified path].
/// </summary>
@@ -477,14 +466,14 @@ namespace MediaBrowser.Controller.Library
/// <param name="query">The query.</param>
/// <returns>List&lt;PersonInfo&gt;.</returns>
List<PersonInfo> GetPeople(InternalPeopleQuery query);
-
+
/// <summary>
/// Gets the people items.
/// </summary>
/// <param name="query">The query.</param>
/// <returns>List&lt;Person&gt;.</returns>
List<Person> GetPeopleItems(InternalPeopleQuery query);
-
+
/// <summary>
/// Gets all people names.
/// </summary>
@@ -559,7 +548,7 @@ namespace MediaBrowser.Controller.Library
/// <param name="query">The query.</param>
/// <returns>QueryResult&lt;BaseItem&gt;.</returns>
QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query);
-
+
/// <summary>
/// Ignores the file.
/// </summary>
@@ -567,5 +556,17 @@ namespace MediaBrowser.Controller.Library
/// <param name="parent">The parent.</param>
/// <returns><c>true</c> if XXXX, <c>false</c> otherwise.</returns>
bool IgnoreFile(FileSystemMetadata file, BaseItem parent);
+
+ void AddVirtualFolder(string name, string collectionType, string[] mediaPaths, bool refreshLibrary);
+ void RemoveVirtualFolder(string name, bool refreshLibrary);
+ void AddMediaPath(string virtualFolderName, string path);
+ void RemoveMediaPath(string virtualFolderName, string path);
+
+ QueryResult<Tuple<BaseItem, ItemCounts>> GetGenres(InternalItemsQuery query);
+ QueryResult<Tuple<BaseItem, ItemCounts>> GetMusicGenres(InternalItemsQuery query);
+ QueryResult<Tuple<BaseItem, ItemCounts>> GetGameGenres(InternalItemsQuery query);
+ QueryResult<Tuple<BaseItem, ItemCounts>> GetStudios(InternalItemsQuery query);
+ QueryResult<Tuple<BaseItem, ItemCounts>> GetArtists(InternalItemsQuery query);
+ QueryResult<Tuple<BaseItem, ItemCounts>> GetAlbumArtists(InternalItemsQuery query);
}
} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Library/IUserDataManager.cs b/MediaBrowser.Controller/Library/IUserDataManager.cs
index 56ac14e9d..86c52c4c3 100644
--- a/MediaBrowser.Controller/Library/IUserDataManager.cs
+++ b/MediaBrowser.Controller/Library/IUserDataManager.cs
@@ -29,21 +29,10 @@ namespace MediaBrowser.Controller.Library
/// <returns>Task.</returns>
Task SaveUserData(Guid userId, IHasUserData item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken);
- /// <summary>
- /// Gets the user data.
- /// </summary>
- /// <param name="userId">The user id.</param>
- /// <param name="key">The key.</param>
- /// <returns>Task{UserItemData}.</returns>
- UserItemData GetUserData(string userId, string key);
+ UserItemData GetUserData(IHasUserData user, IHasUserData item);
- /// <summary>
- /// Gets the user data.
- /// </summary>
- /// <param name="userId">The user id.</param>
- /// <param name="key">The key.</param>
- /// <returns>Task{UserItemData}.</returns>
- UserItemData GetUserData(Guid userId, string key);
+ UserItemData GetUserData(string userId, IHasUserData item);
+ UserItemData GetUserData(Guid userId, IHasUserData item);
/// <summary>
/// Gets the user data dto.
@@ -51,7 +40,9 @@ namespace MediaBrowser.Controller.Library
/// <param name="item">The item.</param>
/// <param name="user">The user.</param>
/// <returns>UserItemDataDto.</returns>
- UserItemDataDto GetUserDataDto(IHasUserData item, User user);
+ Task<UserItemDataDto> GetUserDataDto(IHasUserData item, User user);
+
+ Task<UserItemDataDto> GetUserDataDto(IHasUserData item, BaseItemDto itemDto, User user);
/// <summary>
/// Get all user data for the given user
diff --git a/MediaBrowser.Controller/Library/TVUtils.cs b/MediaBrowser.Controller/Library/TVUtils.cs
index f8039b2cf..29421ebaf 100644
--- a/MediaBrowser.Controller/Library/TVUtils.cs
+++ b/MediaBrowser.Controller/Library/TVUtils.cs
@@ -15,7 +15,7 @@ namespace MediaBrowser.Controller.Library
/// <summary>
/// The banner URL
/// </summary>
- public static readonly string BannerUrl = "http://www.thetvdb.com/banners/";
+ public static readonly string BannerUrl = "https://www.thetvdb.com/banners/";
/// <summary>
/// Gets the air days.
diff --git a/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs b/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs
index ba328ff75..654c6b581 100644
--- a/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs
+++ b/MediaBrowser.Controller/Library/UserDataSaveEventArgs.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Entities;
using System;
+using System.Collections.Generic;
namespace MediaBrowser.Controller.Library
{
@@ -15,11 +16,7 @@ namespace MediaBrowser.Controller.Library
/// <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; }
+ public List<string> Keys { get; set; }
/// <summary>
/// Gets or sets the save reason.
diff --git a/MediaBrowser.Controller/LiveTv/ChannelInfo.cs b/MediaBrowser.Controller/LiveTv/ChannelInfo.cs
index 7d8df96ed..372b095fd 100644
--- a/MediaBrowser.Controller/LiveTv/ChannelInfo.cs
+++ b/MediaBrowser.Controller/LiveTv/ChannelInfo.cs
@@ -59,5 +59,9 @@ namespace MediaBrowser.Controller.LiveTv
/// </summary>
/// <value><c>null</c> if [is favorite] contains no value, <c>true</c> if [is favorite]; otherwise, <c>false</c>.</value>
public bool? IsFavorite { get; set; }
+
+ public bool? IsHD { get; set; }
+ public string AudioCodec { get; set; }
+ public string VideoCodec { get; set; }
}
}
diff --git a/MediaBrowser.Controller/LiveTv/IListingsProvider.cs b/MediaBrowser.Controller/LiveTv/IListingsProvider.cs
index f5048bdda..5ecd70cc5 100644
--- a/MediaBrowser.Controller/LiveTv/IListingsProvider.cs
+++ b/MediaBrowser.Controller/LiveTv/IListingsProvider.cs
@@ -15,5 +15,6 @@ namespace MediaBrowser.Controller.LiveTv
Task AddMetadata(ListingsProviderInfo info, List<ChannelInfo> channels, CancellationToken cancellationToken);
Task Validate(ListingsProviderInfo info, bool validateLogin, bool validateListings);
Task<List<NameIdPair>> GetLineups(ListingsProviderInfo info, string country, string location);
+ Task<List<ChannelInfo>> GetChannels(ListingsProviderInfo info, CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
index 56b7a307a..fe69b38cb 100644
--- a/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
+++ b/MediaBrowser.Controller/LiveTv/ILiveTvManager.cs
@@ -8,6 +8,7 @@ using MediaBrowser.Model.Querying;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Model.Events;
namespace MediaBrowser.Controller.LiveTv
{
@@ -344,6 +345,13 @@ namespace MediaBrowser.Controller.LiveTv
/// <param name="validateListings">if set to <c>true</c> [validate listings].</param>
/// <returns>Task.</returns>
Task<ListingsProviderInfo> SaveListingProvider(ListingsProviderInfo info, bool validateLogin, bool validateListings);
+
+ void DeleteListingsProvider(string id);
+
+ Task<TunerChannelMapping> SetChannelMapping(string providerId, string tunerChannelNumber, string providerChannelNumber);
+
+ TunerChannelMapping GetTunerChannelMapping(ChannelInfo channel, List<NameValuePair> mappings, List<ChannelInfo> providerChannels);
+
/// <summary>
/// Gets the lineups.
/// </summary>
@@ -383,5 +391,17 @@ namespace MediaBrowser.Controller.LiveTv
/// </summary>
/// <returns>List&lt;NameValuePair&gt;.</returns>
List<NameValuePair> GetSatIniMappings();
+
+ Task<List<ChannelInfo>> GetSatChannelScanResult(TunerHostInfo info, CancellationToken cancellationToken);
+
+ Task<List<ChannelInfo>> GetChannelsForListingsProvider(string id, CancellationToken cancellationToken);
+ Task<List<ChannelInfo>> GetChannelsFromListingsProviderData(string id, CancellationToken cancellationToken);
+
+ List<IListingsProvider> ListingProviders { get;}
+
+ event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCancelled;
+ event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCancelled;
+ event EventHandler<GenericEventArgs<TimerEventInfo>> TimerCreated;
+ event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCreated;
}
}
diff --git a/MediaBrowser.Controller/LiveTv/ILiveTvService.cs b/MediaBrowser.Controller/LiveTv/ILiveTvService.cs
index 4ef4847a3..d7d8336d0 100644
--- a/MediaBrowser.Controller/LiveTv/ILiveTvService.cs
+++ b/MediaBrowser.Controller/LiveTv/ILiveTvService.cs
@@ -226,4 +226,23 @@ namespace MediaBrowser.Controller.LiveTv
/// <returns>Task.</returns>
Task ResetTuner(string id, CancellationToken cancellationToken);
}
+
+ public interface ISupportsNewTimerIds
+ {
+ /// <summary>
+ /// Creates the timer asynchronous.
+ /// </summary>
+ /// <param name="info">The information.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ Task<string> CreateTimer(TimerInfo info, CancellationToken cancellationToken);
+
+ /// <summary>
+ /// Creates the series timer asynchronous.
+ /// </summary>
+ /// <param name="info">The information.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
+ /// <returns>Task.</returns>
+ Task<string> CreateSeriesTimer(SeriesTimerInfo info, CancellationToken cancellationToken);
+ }
}
diff --git a/MediaBrowser.Controller/LiveTv/ITunerHost.cs b/MediaBrowser.Controller/LiveTv/ITunerHost.cs
index 498602ddf..1e7aa3de5 100644
--- a/MediaBrowser.Controller/LiveTv/ITunerHost.cs
+++ b/MediaBrowser.Controller/LiveTv/ITunerHost.cs
@@ -46,6 +46,8 @@ namespace MediaBrowser.Controller.LiveTv
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task&lt;List&lt;MediaSourceInfo&gt;&gt;.</returns>
Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken);
+
+ string ApplyDuration(string streamPath, TimeSpan duration);
}
public interface IConfigurableTunerHost
{
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs
index 17a27eac1..e6f472414 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs
@@ -46,17 +46,6 @@ namespace MediaBrowser.Controller.LiveTv
}
/// <summary>
- /// Gets the user data key.
- /// </summary>
- /// <returns>System.String.</returns>
- protected override string CreateUserDataKey()
- {
- var name = GetClientTypeName();
-
- return name + "-" + Name + (EpisodeTitle ?? string.Empty);
- }
-
- /// <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>
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
index 35b9a1959..50aeed27d 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
@@ -11,13 +11,12 @@ namespace MediaBrowser.Controller.LiveTv
{
public class LiveTvChannel : BaseItem, IHasMediaSources
{
- /// <summary>
- /// Gets the user data key.
- /// </summary>
- /// <returns>System.String.</returns>
- protected override string CreateUserDataKey()
+ public override List<string> GetUserDataKeys()
{
- return GetClientTypeName() + "-" + Name;
+ var list = base.GetUserDataKeys();
+
+ list.Insert(0, GetClientTypeName() + "-" + Name);
+ return list;
}
public override UnratedItem GetBlockUnratedType()
@@ -45,6 +44,15 @@ namespace MediaBrowser.Controller.LiveTv
set { }
}
+ [IgnoreDataMember]
+ public override bool EnableRememberingTrackSelections
+ {
+ get
+ {
+ return false;
+ }
+ }
+
/// <summary>
/// Gets or sets the number.
/// </summary>
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
index 59b921c6a..74c993248 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
@@ -4,36 +4,41 @@ using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.LiveTv;
using System;
+using System.Collections.Generic;
using System.Runtime.Serialization;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
namespace MediaBrowser.Controller.LiveTv
{
public class LiveTvProgram : BaseItem, IHasLookupInfo<LiveTvProgramLookupInfo>, IHasStartDate, IHasProgramAttributes
{
- /// <summary>
- /// Gets the user data key.
- /// </summary>
- /// <returns>System.String.</returns>
- protected override string CreateUserDataKey()
+ public override List<string> GetUserDataKeys()
{
- if (IsMovie)
+ var list = base.GetUserDataKeys();
+
+ if (!IsSeries)
{
- var key = Movie.GetMovieUserDataKey(this);
+ var key = this.GetProviderId(MetadataProviders.Imdb);
+ if (!string.IsNullOrWhiteSpace(key))
+ {
+ list.Insert(0, key);
+ }
+ key = this.GetProviderId(MetadataProviders.Tmdb);
if (!string.IsNullOrWhiteSpace(key))
{
- return key;
+ list.Insert(0, key);
}
}
-
- if (IsSeries && !string.IsNullOrWhiteSpace(EpisodeTitle))
+ else if (!string.IsNullOrWhiteSpace(EpisodeTitle))
{
var name = GetClientTypeName();
- return name + "-" + Name + (EpisodeTitle ?? string.Empty);
+ list.Insert(0, name + "-" + Name + (EpisodeTitle ?? string.Empty));
}
- return base.CreateUserDataKey();
+ return list;
}
[IgnoreDataMember]
@@ -231,5 +236,25 @@ namespace MediaBrowser.Controller.LiveTv
return false;
}
}
+
+ public override List<ExternalUrl> GetRelatedUrls()
+ {
+ var list = base.GetRelatedUrls();
+
+ var imdbId = this.GetProviderId(MetadataProviders.Imdb);
+ if (!string.IsNullOrWhiteSpace(imdbId))
+ {
+ if (IsMovie)
+ {
+ list.Add(new ExternalUrl
+ {
+ Name = "Trakt",
+ Url = string.Format("https://trakt.tv/movies/{0}", imdbId)
+ });
+ }
+ }
+
+ return list;
+ }
}
}
diff --git a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs
index f310a957c..a8c737673 100644
--- a/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs
@@ -45,32 +45,6 @@ namespace MediaBrowser.Controller.LiveTv
set { }
}
- /// <summary>
- /// Gets the user data key.
- /// </summary>
- /// <returns>System.String.</returns>
- protected override string CreateUserDataKey()
- {
- if (IsMovie)
- {
- var key = Movie.GetMovieUserDataKey(this);
-
- if (!string.IsNullOrWhiteSpace(key))
- {
- return key;
- }
- }
-
- if (IsSeries && !string.IsNullOrWhiteSpace(EpisodeTitle))
- {
- var name = GetClientTypeName();
-
- return name + "-" + Name + (EpisodeTitle ?? string.Empty);
- }
-
- return base.CreateUserDataKey();
- }
-
[IgnoreDataMember]
public override string MediaType
{
diff --git a/MediaBrowser.Controller/LiveTv/TimerEventInfo.cs b/MediaBrowser.Controller/LiveTv/TimerEventInfo.cs
new file mode 100644
index 000000000..0e1a05475
--- /dev/null
+++ b/MediaBrowser.Controller/LiveTv/TimerEventInfo.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.LiveTv
+{
+ public class TimerEventInfo
+ {
+ public string Id { get; set; }
+ public string ProgramId { get; set; }
+ }
+}
diff --git a/MediaBrowser.Controller/LiveTv/TunerChannelMapping.cs b/MediaBrowser.Controller/LiveTv/TunerChannelMapping.cs
new file mode 100644
index 000000000..da0527eea
--- /dev/null
+++ b/MediaBrowser.Controller/LiveTv/TunerChannelMapping.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.LiveTv
+{
+ public class TunerChannelMapping
+ {
+ public string Name { get; set; }
+ public string Number { get; set; }
+ public string ProviderChannelNumber { get; set; }
+ public string ProviderChannelName { get; set; }
+ }
+}
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 6f429ed2f..0462117cb 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -75,20 +75,15 @@
</Compile>
<Compile Include="Activity\IActivityManager.cs" />
<Compile Include="Activity\IActivityRepository.cs" />
- <Compile Include="Channels\ChannelAudioItem.cs" />
- <Compile Include="Channels\ChannelFolderItem.cs" />
<Compile Include="Channels\ChannelItemInfo.cs" />
<Compile Include="Channels\ChannelItemResult.cs" />
<Compile Include="Channels\ChannelItemType.cs" />
<Compile Include="Channels\ChannelMediaInfo.cs" />
<Compile Include="Channels\ChannelParentalRating.cs" />
<Compile Include="Channels\ChannelSearchInfo.cs" />
- <Compile Include="Channels\ChannelVideoItem.cs" />
<Compile Include="Channels\IChannel.cs" />
- <Compile Include="Channels\IChannelItem.cs" />
<Compile Include="Channels\IChannelManager.cs" />
<Compile Include="Channels\Channel.cs" />
- <Compile Include="Channels\IChannelMediaItem.cs" />
<Compile Include="Channels\IHasCacheKey.cs" />
<Compile Include="Channels\IIndexableChannel.cs" />
<Compile Include="Channels\InternalAllChannelMediaQuery.cs" />
@@ -147,7 +142,7 @@
<Compile Include="Entities\IHasDisplayOrder.cs" />
<Compile Include="Entities\IHasId.cs" />
<Compile Include="Entities\IHasImages.cs" />
- <Compile Include="Entities\IHasKeywords.cs" />
+ <Compile Include="Entities\KeywordExtensions.cs" />
<Compile Include="Entities\IHasMediaSources.cs" />
<Compile Include="Entities\IHasMetascore.cs" />
<Compile Include="Entities\IHasOriginalTitle.cs" />
@@ -159,7 +154,6 @@
<Compile Include="Entities\IHasSpecialFeatures.cs" />
<Compile Include="Entities\IHasStartDate.cs" />
<Compile Include="Entities\IHasTaglines.cs" />
- <Compile Include="Entities\IHasTags.cs" />
<Compile Include="Entities\IHasThemeMedia.cs" />
<Compile Include="Entities\IHasTrailers.cs" />
<Compile Include="Entities\IHasUserData.cs" />
@@ -182,9 +176,11 @@
<Compile Include="Entities\PhotoAlbum.cs" />
<Compile Include="Entities\Share.cs" />
<Compile Include="Entities\SourceType.cs" />
+ <Compile Include="Entities\TagExtensions.cs" />
<Compile Include="Entities\UserView.cs" />
<Compile Include="Entities\UserViewBuilder.cs" />
<Compile Include="FileOrganization\IFileOrganizationService.cs" />
+ <Compile Include="Health\IHealthMonitor.cs" />
<Compile Include="IO\ThrottledStream.cs" />
<Compile Include="Library\DeleteOptions.cs" />
<Compile Include="Library\ILibraryPostScanTask.cs" />
@@ -222,7 +218,9 @@
<Compile Include="LiveTv\ProgramInfo.cs" />
<Compile Include="LiveTv\RecordingInfo.cs" />
<Compile Include="LiveTv\SeriesTimerInfo.cs" />
+ <Compile Include="LiveTv\TimerEventInfo.cs" />
<Compile Include="LiveTv\TimerInfo.cs" />
+ <Compile Include="LiveTv\TunerChannelMapping.cs" />
<Compile Include="Localization\ILocalizationManager.cs" />
<Compile Include="MediaEncoding\ChapterImageRefreshOptions.cs" />
<Compile Include="MediaEncoding\EncodingJobOptions.cs" />
@@ -294,21 +292,17 @@
<Compile Include="Providers\IImageFileSaver.cs" />
<Compile Include="Providers\IImageProvider.cs" />
<Compile Include="Providers\IImageSaver.cs" />
- <Compile Include="Providers\IItemIdentityConverter.cs" />
- <Compile Include="Providers\IItemIdentityProvider.cs" />
<Compile Include="Providers\ILocalImageFileProvider.cs" />
<Compile Include="Providers\ILocalMetadataProvider.cs" />
<Compile Include="Providers\ImageRefreshMode.cs" />
<Compile Include="Providers\ImageRefreshOptions.cs" />
<Compile Include="Providers\IPreRefreshProvider.cs" />
- <Compile Include="Providers\IProviderRepository.cs" />
<Compile Include="Providers\IRemoteImageProvider.cs" />
<Compile Include="Providers\ILocalImageProvider.cs" />
<Compile Include="Providers\IMetadataProvider.cs" />
<Compile Include="Providers\IMetadataService.cs" />
<Compile Include="Providers\IRemoteMetadataProvider.cs" />
<Compile Include="Providers\IRemoteSearchProvider.cs" />
- <Compile Include="Providers\ISeriesOrderProvider.cs" />
<Compile Include="Providers\ItemInfo.cs" />
<Compile Include="Providers\LiveTvProgramLookupInfo.cs" />
<Compile Include="Providers\LocalImageInfo.cs" />
@@ -334,12 +328,8 @@
<Compile Include="Sorting\SortHelper.cs" />
<Compile Include="Subtitles\ISubtitleManager.cs" />
<Compile Include="Subtitles\ISubtitleProvider.cs" />
- <Compile Include="Providers\ItemIdentifier.cs" />
- <Compile Include="Providers\ItemIdentities.cs" />
<Compile Include="Providers\ItemLookupInfo.cs" />
<Compile Include="Providers\MetadataRefreshOptions.cs" />
- <Compile Include="Providers\MetadataStatus.cs" />
- <Compile Include="Providers\ISeriesOrderManager.cs" />
<Compile Include="Session\ISessionManager.cs" />
<Compile Include="Entities\AggregateFolder.cs" />
<Compile Include="Entities\Audio\Audio.cs" />
diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs
index ddaf7ff6d..44b741755 100644
--- a/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs
+++ b/MediaBrowser.Controller/MediaEncoding/EncodingJobOptions.cs
@@ -1,4 +1,5 @@
-using MediaBrowser.Model.Dlna;
+using System.Linq;
+using MediaBrowser.Model.Dlna;
namespace MediaBrowser.Controller.MediaEncoding
{
@@ -58,8 +59,6 @@ namespace MediaBrowser.Controller.MediaEncoding
}
}
- public bool? Cabac { get; set; }
-
public EncodingJobOptions()
{
@@ -76,7 +75,7 @@ namespace MediaBrowser.Controller.MediaEncoding
Level = info.VideoLevel;
ItemId = info.ItemId;
MediaSourceId = info.MediaSourceId;
- AudioCodec = info.AudioCodec;
+ AudioCodec = info.TargetAudioCodec;
MaxAudioChannels = info.MaxAudioChannels;
AudioBitRate = info.AudioBitrate;
AudioSampleRate = info.TargetAudioSampleRate;
@@ -87,7 +86,6 @@ namespace MediaBrowser.Controller.MediaEncoding
MaxRefFrames = info.MaxRefFrames;
MaxVideoBitDepth = info.MaxVideoBitDepth;
SubtitleMethod = info.SubtitleDeliveryMethod;
- Cabac = info.Cabac;
Context = info.Context;
if (info.SubtitleDeliveryMethod != SubtitleDeliveryMethod.External)
diff --git a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
index 76ef054de..c8a8caa91 100644
--- a/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
+++ b/MediaBrowser.Controller/MediaEncoding/IMediaEncoder.cs
@@ -4,14 +4,17 @@ using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Model.Dlna;
namespace MediaBrowser.Controller.MediaEncoding
{
/// <summary>
/// Interface IMediaEncoder
/// </summary>
- public interface IMediaEncoder
+ public interface IMediaEncoder : ITranscoderSupport
{
+ string EncoderLocationType { get; }
+
/// <summary>
/// Gets the encoder path.
/// </summary>
@@ -19,12 +22,6 @@ namespace MediaBrowser.Controller.MediaEncoding
string EncoderPath { get; }
/// <summary>
- /// Gets the version.
- /// </summary>
- /// <value>The version.</value>
- string Version { get; }
-
- /// <summary>
/// Supportses the decoder.
/// </summary>
/// <param name="decoder">The decoder.</param>
@@ -38,7 +35,7 @@ namespace MediaBrowser.Controller.MediaEncoding
/// <param name="imageStreamIndex">Index of the image stream.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{Stream}.</returns>
- Task<Stream> ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken);
+ Task<string> ExtractAudioImage(string path, int? imageStreamIndex, CancellationToken cancellationToken);
/// <summary>
/// Extracts the video image.
@@ -49,7 +46,9 @@ namespace MediaBrowser.Controller.MediaEncoding
/// <param name="offset">The offset.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{Stream}.</returns>
- Task<Stream> ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken);
+ Task<string> ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, Video3DFormat? threedFormat, TimeSpan? offset, CancellationToken cancellationToken);
+
+ Task<string> ExtractVideoImage(string[] inputFiles, MediaProtocol protocol, int? imageStreamIndex, CancellationToken cancellationToken);
/// <summary>
/// Extracts the video images on interval.
@@ -63,12 +62,12 @@ namespace MediaBrowser.Controller.MediaEncoding
/// <param name="maxWidth">The maximum width.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task ExtractVideoImagesOnInterval(string[] inputFiles,
- MediaProtocol protocol,
- Video3DFormat? threedFormat,
- TimeSpan interval,
- string targetDirectory,
- string filenamePrefix,
+ Task ExtractVideoImagesOnInterval(string[] inputFiles,
+ MediaProtocol protocol,
+ Video3DFormat? threedFormat,
+ TimeSpan interval,
+ string targetDirectory,
+ string filenamePrefix,
int? maxWidth,
CancellationToken cancellationToken);
@@ -131,5 +130,9 @@ namespace MediaBrowser.Controller.MediaEncoding
/// <param name="path">The path.</param>
/// <returns>System.String.</returns>
string EscapeSubtitleFilterPath(string path);
+
+ Task Init();
+
+ Task UpdateEncoderPath(string path, string pathType);
}
}
diff --git a/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs b/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs
index 826711e51..44489cbf5 100644
--- a/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs
+++ b/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs
@@ -10,13 +10,6 @@ namespace MediaBrowser.Controller.MediaEncoding
/// <summary>
/// Gets the subtitles.
/// </summary>
- /// <param name="itemId">The item identifier.</param>
- /// <param name="mediaSourceId">The media source identifier.</param>
- /// <param name="subtitleStreamIndex">Index of the subtitle stream.</param>
- /// <param name="outputFormat">The output format.</param>
- /// <param name="startTimeTicks">The start time ticks.</param>
- /// <param name="endTimeTicks">The end time ticks.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{Stream}.</returns>
Task<Stream> GetSubtitles(string itemId,
string mediaSourceId,
@@ -24,6 +17,7 @@ namespace MediaBrowser.Controller.MediaEncoding
string outputFormat,
long startTimeTicks,
long? endTimeTicks,
+ bool preserveOriginalTimestamps,
CancellationToken cancellationToken);
/// <summary>
@@ -33,6 +27,6 @@ namespace MediaBrowser.Controller.MediaEncoding
/// <param name="protocol">The protocol.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>System.String.</returns>
- Task<string> GetSubtitleFileCharacterSet(string path, MediaProtocol protocol, CancellationToken cancellationToken);
+ Task<string> GetSubtitleFileCharacterSet(string path, string language, MediaProtocol protocol, CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/Net/IHttpResultFactory.cs b/MediaBrowser.Controller/Net/IHttpResultFactory.cs
index 526bf4be2..49d4614d8 100644
--- a/MediaBrowser.Controller/Net/IHttpResultFactory.cs
+++ b/MediaBrowser.Controller/Net/IHttpResultFactory.cs
@@ -28,6 +28,8 @@ namespace MediaBrowser.Controller.Net
/// <returns>System.Object.</returns>
object GetResult(object content, string contentType, IDictionary<string,string> responseHeaders = null);
+ object GetAsyncStreamWriter(Func<Stream,Task> streamWriter, IDictionary<string, string> responseHeaders = null);
+
/// <summary>
/// Gets the optimized result.
/// </summary>
@@ -80,7 +82,7 @@ namespace MediaBrowser.Controller.Net
/// <param name="responseHeaders">The response headers.</param>
/// <param name="isHeadRequest">if set to <c>true</c> [is head request].</param>
/// <returns>System.Object.</returns>
- object GetStaticResult(IRequest requestContext,
+ Task<object> GetStaticResult(IRequest requestContext,
Guid cacheKey,
DateTime? lastDateModified,
TimeSpan? cacheDuration,
@@ -94,7 +96,7 @@ namespace MediaBrowser.Controller.Net
/// <param name="requestContext">The request context.</param>
/// <param name="options">The options.</param>
/// <returns>System.Object.</returns>
- object GetStaticResult(IRequest requestContext, StaticResultOptions options);
+ Task<object> GetStaticResult(IRequest requestContext, StaticResultOptions options);
/// <summary>
/// Gets the static file result.
@@ -103,7 +105,7 @@ namespace MediaBrowser.Controller.Net
/// <param name="path">The path.</param>
/// <param name="fileShare">The file share.</param>
/// <returns>System.Object.</returns>
- object GetStaticFileResult(IRequest requestContext, string path, FileShare fileShare = FileShare.Read);
+ Task<object> GetStaticFileResult(IRequest requestContext, string path, FileShare fileShare = FileShare.Read);
/// <summary>
/// Gets the static file result.
@@ -111,7 +113,7 @@ namespace MediaBrowser.Controller.Net
/// <param name="requestContext">The request context.</param>
/// <param name="options">The options.</param>
/// <returns>System.Object.</returns>
- object GetStaticFileResult(IRequest requestContext,
+ Task<object> GetStaticFileResult(IRequest requestContext,
StaticFileResultOptions options);
}
}
diff --git a/MediaBrowser.Controller/Notifications/INotificationsRepository.cs b/MediaBrowser.Controller/Notifications/INotificationsRepository.cs
index 6ad4a5377..cd587a509 100644
--- a/MediaBrowser.Controller/Notifications/INotificationsRepository.cs
+++ b/MediaBrowser.Controller/Notifications/INotificationsRepository.cs
@@ -19,12 +19,6 @@ namespace MediaBrowser.Controller.Notifications
/// Occurs when [notifications marked read].
/// </summary>
event EventHandler<NotificationReadEventArgs> NotificationsMarkedRead;
-
- /// <summary>
- /// Opens the connection to the repository
- /// </summary>
- /// <returns>Task.</returns>
- Task Initialize();
/// <summary>
/// Gets the notifications.
diff --git a/MediaBrowser.Controller/Persistence/IDisplayPreferencesRepository.cs b/MediaBrowser.Controller/Persistence/IDisplayPreferencesRepository.cs
index 17de730cb..abf96994f 100644
--- a/MediaBrowser.Controller/Persistence/IDisplayPreferencesRepository.cs
+++ b/MediaBrowser.Controller/Persistence/IDisplayPreferencesRepository.cs
@@ -12,12 +12,6 @@ namespace MediaBrowser.Controller.Persistence
public interface IDisplayPreferencesRepository : IRepository
{
/// <summary>
- /// Opens the connection to the repository
- /// </summary>
- /// <returns>Task.</returns>
- Task Initialize();
-
- /// <summary>
/// Saves display preferences for an item
/// </summary>
/// <param name="displayPreferences">The display preferences.</param>
diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs
index 15df1f649..78138999c 100644
--- a/MediaBrowser.Controller/Persistence/IItemRepository.cs
+++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs
@@ -4,6 +4,7 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
+using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
namespace MediaBrowser.Controller.Persistence
@@ -14,12 +15,6 @@ namespace MediaBrowser.Controller.Persistence
public interface IItemRepository : IRepository
{
/// <summary>
- /// Opens the connection to the repository
- /// </summary>
- /// <returns>Task.</returns>
- Task Initialize();
-
- /// <summary>
/// Saves an item
/// </summary>
/// <param name="item">The item.</param>
@@ -87,7 +82,7 @@ namespace MediaBrowser.Controller.Persistence
/// <param name="chapters">The chapters.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task SaveChapters(Guid id, IEnumerable<ChapterInfo> chapters, CancellationToken cancellationToken);
+ Task SaveChapters(Guid id, List<ChapterInfo> chapters, CancellationToken cancellationToken);
/// <summary>
/// Gets the media streams.
@@ -103,7 +98,7 @@ namespace MediaBrowser.Controller.Persistence
/// <param name="streams">The streams.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- Task SaveMediaStreams(Guid id, IEnumerable<MediaStream> streams, CancellationToken cancellationToken);
+ Task SaveMediaStreams(Guid id, List<MediaStream> streams, CancellationToken cancellationToken);
/// <summary>
/// Gets the item ids.
@@ -159,7 +154,7 @@ namespace MediaBrowser.Controller.Persistence
/// </summary>
/// <param name="query">The query.</param>
/// <returns>List&lt;BaseItem&gt;.</returns>
- IEnumerable<BaseItem> GetItemList(InternalItemsQuery query);
+ List<BaseItem> GetItemList(InternalItemsQuery query);
/// <summary>
/// Updates the inherited values.
@@ -167,6 +162,13 @@ namespace MediaBrowser.Controller.Persistence
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
Task UpdateInheritedValues(CancellationToken cancellationToken);
+
+ QueryResult<Tuple<BaseItem, ItemCounts>> GetGenres(InternalItemsQuery query);
+ QueryResult<Tuple<BaseItem, ItemCounts>> GetMusicGenres(InternalItemsQuery query);
+ QueryResult<Tuple<BaseItem, ItemCounts>> GetGameGenres(InternalItemsQuery query);
+ QueryResult<Tuple<BaseItem, ItemCounts>> GetStudios(InternalItemsQuery query);
+ QueryResult<Tuple<BaseItem, ItemCounts>> GetArtists(InternalItemsQuery query);
+ QueryResult<Tuple<BaseItem, ItemCounts>> GetAlbumArtists(InternalItemsQuery query);
}
}
diff --git a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs b/MediaBrowser.Controller/Persistence/IUserDataRepository.cs
index 2a904be0d..ca4dc9751 100644
--- a/MediaBrowser.Controller/Persistence/IUserDataRepository.cs
+++ b/MediaBrowser.Controller/Persistence/IUserDataRepository.cs
@@ -12,12 +12,6 @@ namespace MediaBrowser.Controller.Persistence
public interface IUserDataRepository : IRepository
{
/// <summary>
- /// Opens the connection to the repository
- /// </summary>
- /// <returns>Task.</returns>
- Task Initialize();
-
- /// <summary>
/// Saves the user data.
/// </summary>
/// <param name="userId">The user id.</param>
@@ -35,6 +29,8 @@ namespace MediaBrowser.Controller.Persistence
/// <returns>Task{UserItemData}.</returns>
UserItemData GetUserData(Guid userId, string key);
+ UserItemData GetUserData(Guid userId, List<string> keys);
+
/// <summary>
/// Return all user data associated with the given user
/// </summary>
diff --git a/MediaBrowser.Controller/Playlists/Playlist.cs b/MediaBrowser.Controller/Playlists/Playlist.cs
index 0f9af6550..5ffe3d5da 100644
--- a/MediaBrowser.Controller/Playlists/Playlist.cs
+++ b/MediaBrowser.Controller/Playlists/Playlist.cs
@@ -6,6 +6,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
+using System.Threading.Tasks;
namespace MediaBrowser.Controller.Playlists
{
@@ -38,6 +39,15 @@ namespace MediaBrowser.Controller.Playlists
}
}
+ [IgnoreDataMember]
+ public override bool SupportsCumulativeRunTimeTicks
+ {
+ get
+ {
+ return true;
+ }
+ }
+
public override bool IsAuthorizedToDelete(User user)
{
return true;
@@ -50,16 +60,16 @@ namespace MediaBrowser.Controller.Playlists
public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
{
- return GetPlayableItems(user);
+ return GetPlayableItems(user).Result;
}
- public override IEnumerable<BaseItem> GetRecursiveChildren(User user, Func<BaseItem, bool> filter)
+ public override IEnumerable<BaseItem> GetRecursiveChildren(User user, InternalItemsQuery query)
{
- var items = GetPlayableItems(user);
+ var items = GetPlayableItems(user).Result;
- if (filter != null)
+ if (query != null)
{
- items = items.Where(filter);
+ items = items.Where(i => UserViewBuilder.FilterItem(i, query));
}
return items;
@@ -70,32 +80,40 @@ namespace MediaBrowser.Controller.Playlists
return GetLinkedChildrenInfos();
}
- private IEnumerable<BaseItem> GetPlayableItems(User user)
+ private Task<IEnumerable<BaseItem>> GetPlayableItems(User user)
{
return GetPlaylistItems(MediaType, base.GetChildren(user, true), user);
}
- public static IEnumerable<BaseItem> GetPlaylistItems(string playlistMediaType, IEnumerable<BaseItem> inputItems, User user)
+ public static async Task<IEnumerable<BaseItem>> GetPlaylistItems(string playlistMediaType, IEnumerable<BaseItem> inputItems, User user)
{
if (user != null)
{
inputItems = inputItems.Where(i => i.IsVisible(user));
}
- return inputItems.SelectMany(i => GetPlaylistItems(i, user))
- .Where(m => string.Equals(m.MediaType, playlistMediaType, StringComparison.OrdinalIgnoreCase));
+ var list = new List<BaseItem>();
+
+ foreach (var item in inputItems)
+ {
+ var playlistItems = await GetPlaylistItems(item, user, playlistMediaType).ConfigureAwait(false);
+ list.AddRange(playlistItems);
+ }
+
+ return list;
}
- private static IEnumerable<BaseItem> GetPlaylistItems(BaseItem item, User user)
+ private static async Task<IEnumerable<BaseItem>> GetPlaylistItems(BaseItem item, User user, string mediaType)
{
var musicGenre = item as MusicGenre;
if (musicGenre != null)
{
- Func<BaseItem, bool> filter = i => i is Audio && i.Genres.Contains(musicGenre.Name, StringComparer.OrdinalIgnoreCase);
-
- var items = user == null
- ? LibraryManager.RootFolder.GetRecursiveChildren(filter)
- : user.RootFolder.GetRecursiveChildren(user, filter);
+ var items = LibraryManager.GetItemList(new InternalItemsQuery(user)
+ {
+ Recursive = true,
+ IncludeItemTypes = new[] { typeof(Audio).Name },
+ Genres = new[] { musicGenre.Name }
+ });
return LibraryManager.Sort(items, user, new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }, SortOrder.Ascending);
}
@@ -111,7 +129,11 @@ namespace MediaBrowser.Controller.Playlists
var items = user == null
? LibraryManager.RootFolder.GetRecursiveChildren(filter)
- : user.RootFolder.GetRecursiveChildren(user, filter);
+ : user.RootFolder.GetRecursiveChildren(user, new InternalItemsQuery(user)
+ {
+ IncludeItemTypes = new[] { typeof(Audio).Name },
+ ArtistNames = new[] { musicArtist.Name }
+ });
return LibraryManager.Sort(items, user, new[] { ItemSortBy.AlbumArtist, ItemSortBy.Album, ItemSortBy.SortName }, SortOrder.Ascending);
}
@@ -119,15 +141,19 @@ namespace MediaBrowser.Controller.Playlists
var folder = item as Folder;
if (folder != null)
{
- var items = user == null
- ? folder.GetRecursiveChildren(m => !m.IsFolder)
- : folder.GetRecursiveChildren(user, m => !m.IsFolder);
-
- if (folder.IsPreSorted)
+ var query = new InternalItemsQuery(user)
{
- return items;
- }
- return LibraryManager.Sort(items, user, new[] { ItemSortBy.SortName }, SortOrder.Ascending);
+ Recursive = true,
+ IsFolder = false,
+ SortBy = new[] { ItemSortBy.SortName },
+ MediaTypes = new[] { mediaType },
+ EnableTotalRecordCount = false
+ };
+
+ var itemsResult = await folder.GetItems(query).ConfigureAwait(false);
+ var items = itemsResult.Items;
+
+ return items;
}
return new[] { item };
diff --git a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
index f9060d184..a783910e3 100644
--- a/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
+++ b/MediaBrowser.Controller/Providers/BaseItemXmlParser.cs
@@ -61,16 +61,7 @@ namespace MediaBrowser.Controller.Providers
};
//Fetch(item, metadataFile, settings, Encoding.GetEncoding("ISO-8859-1"), cancellationToken);
-
- try
- {
- Fetch(item, metadataFile, settings, Encoding.UTF8, cancellationToken);
- }
- catch
- {
- Logger.Error("Error parsing xml file {0}", metadataFile);
- throw;
- }
+ Fetch(item, metadataFile, settings, Encoding.UTF8, cancellationToken);
}
/// <summary>
@@ -812,11 +803,7 @@ namespace MediaBrowser.Controller.Providers
{
using (var subtree = reader.ReadSubtree())
{
- var hasTags = item as IHasTags;
- if (hasTags != null)
- {
- FetchFromTagsNode(subtree, hasTags);
- }
+ FetchFromTagsNode(subtree, item);
}
break;
}
@@ -825,11 +812,7 @@ namespace MediaBrowser.Controller.Providers
{
using (var subtree = reader.ReadSubtree())
{
- var hasTags = item as IHasKeywords;
- if (hasTags != null)
- {
- FetchFromKeywordsNode(subtree, hasTags);
- }
+ FetchFromKeywordsNode(subtree, item);
}
break;
}
@@ -1079,7 +1062,7 @@ namespace MediaBrowser.Controller.Providers
}
}
- private void FetchFromTagsNode(XmlReader reader, IHasTags item)
+ private void FetchFromTagsNode(XmlReader reader, BaseItem item)
{
reader.MoveToContent();
@@ -1108,7 +1091,7 @@ namespace MediaBrowser.Controller.Providers
}
}
- private void FetchFromKeywordsNode(XmlReader reader, IHasKeywords item)
+ private void FetchFromKeywordsNode(XmlReader reader, BaseItem item)
{
reader.MoveToContent();
diff --git a/MediaBrowser.Controller/Providers/DirectoryService.cs b/MediaBrowser.Controller/Providers/DirectoryService.cs
index c057c9707..e7e3323c2 100644
--- a/MediaBrowser.Controller/Providers/DirectoryService.cs
+++ b/MediaBrowser.Controller/Providers/DirectoryService.cs
@@ -102,6 +102,12 @@ namespace MediaBrowser.Controller.Providers
{
var directory = Path.GetDirectoryName(path);
+ if (string.IsNullOrWhiteSpace(directory))
+ {
+ _logger.Debug("Parent path is null for {0}", path);
+ return null;
+ }
+
var dict = GetFileSystemDictionary(directory, false);
FileSystemMetadata entry;
diff --git a/MediaBrowser.Controller/Providers/EpisodeInfo.cs b/MediaBrowser.Controller/Providers/EpisodeInfo.cs
index 28abd636a..b879040f8 100644
--- a/MediaBrowser.Controller/Providers/EpisodeInfo.cs
+++ b/MediaBrowser.Controller/Providers/EpisodeInfo.cs
@@ -10,6 +10,9 @@ namespace MediaBrowser.Controller.Providers
public int? IndexNumberEnd { get; set; }
public int? AnimeSeriesIndex { get; set; }
+ public bool IsMissingEpisode { get; set; }
+ public bool IsVirtualUnaired { get; set; }
+
public EpisodeInfo()
{
SeriesProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
diff --git a/MediaBrowser.Controller/Providers/IHasItemChangeMonitor.cs b/MediaBrowser.Controller/Providers/IHasItemChangeMonitor.cs
index 4c7069dd6..9441c3ecd 100644
--- a/MediaBrowser.Controller/Providers/IHasItemChangeMonitor.cs
+++ b/MediaBrowser.Controller/Providers/IHasItemChangeMonitor.cs
@@ -8,9 +8,8 @@ namespace MediaBrowser.Controller.Providers
/// Determines whether the specified item has changed.
/// </summary>
/// <param name="item">The item.</param>
- /// <param name="status">The status.</param>
/// <param name="directoryService">The directory service.</param>
/// <returns><c>true</c> if the specified item has changed; otherwise, <c>false</c>.</returns>
- bool HasChanged(IHasMetadata item, MetadataStatus status, IDirectoryService directoryService);
+ bool HasChanged(IHasMetadata item, IDirectoryService directoryService);
}
} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Providers/IItemIdentityConverter.cs b/MediaBrowser.Controller/Providers/IItemIdentityConverter.cs
deleted file mode 100644
index bfdd1dbf3..000000000
--- a/MediaBrowser.Controller/Providers/IItemIdentityConverter.cs
+++ /dev/null
@@ -1,4 +0,0 @@
-namespace MediaBrowser.Controller.Providers
-{
- public interface IItemIdentityConverter { }
-} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Providers/IItemIdentityProvider.cs b/MediaBrowser.Controller/Providers/IItemIdentityProvider.cs
deleted file mode 100644
index 6b403bb55..000000000
--- a/MediaBrowser.Controller/Providers/IItemIdentityProvider.cs
+++ /dev/null
@@ -1,4 +0,0 @@
-namespace MediaBrowser.Controller.Providers
-{
- public interface IItemIdentityProvider { }
-} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Providers/IProviderManager.cs b/MediaBrowser.Controller/Providers/IProviderManager.cs
index 57e4ff320..3eefa9647 100644
--- a/MediaBrowser.Controller/Providers/IProviderManager.cs
+++ b/MediaBrowser.Controller/Providers/IProviderManager.cs
@@ -97,13 +97,11 @@ namespace MediaBrowser.Controller.Providers
/// </summary>
/// <param name="imageProviders">The image providers.</param>
/// <param name="metadataServices">The metadata services.</param>
- /// <param name="identityProviders">The identity providers.</param>
- /// <param name="identityConverters">The identity converters.</param>
/// <param name="metadataProviders">The metadata providers.</param>
/// <param name="savers">The savers.</param>
/// <param name="imageSavers">The image savers.</param>
/// <param name="externalIds">The external ids.</param>
- void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IItemIdentityProvider> identityProviders, IEnumerable<IItemIdentityConverter> identityConverters, IEnumerable<IMetadataProvider> metadataProviders,
+ void AddParts(IEnumerable<IImageProvider> imageProviders, IEnumerable<IMetadataService> metadataServices, IEnumerable<IMetadataProvider> metadataProviders,
IEnumerable<IMetadataSaver> savers,
IEnumerable<IImageSaver> imageSavers,
IEnumerable<IExternalId> externalIds);
@@ -135,7 +133,7 @@ namespace MediaBrowser.Controller.Providers
/// </summary>
/// <param name="item">The item.</param>
/// <returns>IEnumerable{ExternalUrl}.</returns>
- IEnumerable<ExternalUrl> GetExternalUrls(IHasProviderIds item);
+ IEnumerable<ExternalUrl> GetExternalUrls(BaseItem item);
/// <summary>
/// Gets the external identifier infos.
@@ -190,21 +188,5 @@ namespace MediaBrowser.Controller.Providers
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{HttpResponseInfo}.</returns>
Task<HttpResponseInfo> GetSearchImage(string providerName, string url, CancellationToken cancellationToken);
-
- /// <summary>
- /// Gets the item identity providers.
- /// </summary>
- /// <typeparam name="TLookupInfo">The type of the t lookup information.</typeparam>
- /// <returns>IEnumerable&lt;IItemIdentityProvider&lt;TLookupInfo, TIdentity&gt;&gt;.</returns>
- IEnumerable<IItemIdentityProvider<TLookupInfo>> GetItemIdentityProviders<TLookupInfo>()
- where TLookupInfo : ItemLookupInfo;
-
- /// <summary>
- /// Gets the item identity converters.
- /// </summary>
- /// <typeparam name="TLookupInfo">The type of the t lookup information.</typeparam>
- /// <returns>IEnumerable&lt;IItemIdentityConverter&lt;TIdentity&gt;&gt;.</returns>
- IEnumerable<IItemIdentityConverter<TLookupInfo>> GetItemIdentityConverters<TLookupInfo>()
- where TLookupInfo : ItemLookupInfo;
}
} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Providers/IProviderRepository.cs b/MediaBrowser.Controller/Providers/IProviderRepository.cs
deleted file mode 100644
index 1f77d0ca1..000000000
--- a/MediaBrowser.Controller/Providers/IProviderRepository.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-using MediaBrowser.Controller.Persistence;
-using System;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Controller.Providers
-{
- public interface IProviderRepository : IRepository
- {
- /// <summary>
- /// Gets the metadata status.
- /// </summary>
- /// <param name="itemId">The item identifier.</param>
- /// <returns>MetadataStatus.</returns>
- MetadataStatus GetMetadataStatus(Guid itemId);
-
- /// <summary>
- /// Saves the metadata status.
- /// </summary>
- /// <param name="status">The status.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
- /// <returns>Task.</returns>
- Task SaveMetadataStatus(MetadataStatus status, CancellationToken cancellationToken);
-
- /// <summary>
- /// Initializes this instance.
- /// </summary>
- /// <returns>Task.</returns>
- Task Initialize();
- }
-}
diff --git a/MediaBrowser.Controller/Providers/ISeriesOrderManager.cs b/MediaBrowser.Controller/Providers/ISeriesOrderManager.cs
deleted file mode 100644
index 970f7a7be..000000000
--- a/MediaBrowser.Controller/Providers/ISeriesOrderManager.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using System.Collections.Generic;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Controller.Providers
-{
- public interface ISeriesOrderManager
- {
- Task<int?> FindSeriesIndex(string orderType, string seriesName);
- void AddParts(IEnumerable<ISeriesOrderProvider> orderProviders);
- }
-}
diff --git a/MediaBrowser.Controller/Providers/ISeriesOrderProvider.cs b/MediaBrowser.Controller/Providers/ISeriesOrderProvider.cs
deleted file mode 100644
index ee0f3c197..000000000
--- a/MediaBrowser.Controller/Providers/ISeriesOrderProvider.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Controller.Providers
-{
- public interface ISeriesOrderProvider
- {
- string OrderType { get; }
- Task<int?> FindSeriesIndex(string seriesName);
- }
-} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Providers/ItemIdentifier.cs b/MediaBrowser.Controller/Providers/ItemIdentifier.cs
deleted file mode 100644
index bbc6dd76c..000000000
--- a/MediaBrowser.Controller/Providers/ItemIdentifier.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Controller.Providers
-{
- public static class ItemIdentifier<TLookupInfo>
- where TLookupInfo : ItemLookupInfo
- {
- public static async Task FindIdentities(TLookupInfo item, IProviderManager providerManager, CancellationToken cancellationToken)
- {
- var providers = providerManager.GetItemIdentityProviders<TLookupInfo>();
- var converters = providerManager.GetItemIdentityConverters<TLookupInfo>().ToList();
-
- foreach (var provider in providers)
- {
- await provider.Identify(item);
- }
-
- bool changesMade = true;
-
- while (changesMade)
- {
- changesMade = false;
-
- foreach (var converter in converters)
- {
- if (await converter.Convert(item))
- {
- changesMade = true;
- }
- }
- }
- }
- }
-} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Providers/ItemIdentities.cs b/MediaBrowser.Controller/Providers/ItemIdentities.cs
deleted file mode 100644
index 48316d0f4..000000000
--- a/MediaBrowser.Controller/Providers/ItemIdentities.cs
+++ /dev/null
@@ -1,16 +0,0 @@
-using System.Threading.Tasks;
-
-namespace MediaBrowser.Controller.Providers
-{
- public interface IItemIdentityProvider<in TLookupInfo> : IItemIdentityProvider
- where TLookupInfo : ItemLookupInfo
- {
- Task Identify(TLookupInfo info);
- }
-
- public interface IItemIdentityConverter<in TLookupInfo> : IItemIdentityConverter
- where TLookupInfo : ItemLookupInfo
- {
- Task<bool> Convert(TLookupInfo info);
- }
-} \ No newline at end of file
diff --git a/MediaBrowser.Controller/Providers/ItemInfo.cs b/MediaBrowser.Controller/Providers/ItemInfo.cs
index d16a73028..63cc48058 100644
--- a/MediaBrowser.Controller/Providers/ItemInfo.cs
+++ b/MediaBrowser.Controller/Providers/ItemInfo.cs
@@ -1,3 +1,4 @@
+using System;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Entities;
@@ -5,10 +6,6 @@ namespace MediaBrowser.Controller.Providers
{
public class ItemInfo
{
- public ItemInfo()
- {
- }
-
public ItemInfo(IHasMetadata item)
{
Path = item.Path;
@@ -21,8 +18,11 @@ namespace MediaBrowser.Controller.Providers
VideoType = video.VideoType;
IsPlaceHolder = video.IsPlaceHolder;
}
+
+ ItemType = item.GetType();
}
+ public Type ItemType { get; set; }
public string Path { get; set; }
public string ContainingFolderPath { get; set; }
public VideoType VideoType { get; set; }
diff --git a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs
index 29f4feb3d..9427b2afd 100644
--- a/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs
+++ b/MediaBrowser.Controller/Providers/MetadataRefreshOptions.cs
@@ -1,5 +1,6 @@
using System.Linq;
using CommonIO;
+using MediaBrowser.Model.Providers;
namespace MediaBrowser.Controller.Providers
{
@@ -13,6 +14,7 @@ namespace MediaBrowser.Controller.Providers
public bool IsPostRecursiveRefresh { get; set; }
public MetadataRefreshMode MetadataRefreshMode { get; set; }
+ public RemoteSearchResult SearchResult { get; set; }
public bool ForceSave { get; set; }
@@ -37,6 +39,7 @@ namespace MediaBrowser.Controller.Providers
ImageRefreshMode = copy.ImageRefreshMode;
ReplaceAllImages = copy.ReplaceAllImages;
ReplaceImages = copy.ReplaceImages.ToList();
+ SearchResult = copy.SearchResult;
}
}
}
diff --git a/MediaBrowser.Controller/Providers/MetadataStatus.cs b/MediaBrowser.Controller/Providers/MetadataStatus.cs
deleted file mode 100644
index b19377a68..000000000
--- a/MediaBrowser.Controller/Providers/MetadataStatus.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-using System;
-
-namespace MediaBrowser.Controller.Providers
-{
- public class MetadataStatus
- {
- /// <summary>
- /// Gets or sets the item identifier.
- /// </summary>
- /// <value>The item identifier.</value>
- public Guid ItemId { get; set; }
-
- /// <summary>
- /// Gets or sets the date last metadata refresh.
- /// </summary>
- /// <value>The date last metadata refresh.</value>
- public DateTime? DateLastMetadataRefresh { get; set; }
-
- /// <summary>
- /// Gets or sets the date last images refresh.
- /// </summary>
- /// <value>The date last images refresh.</value>
- public DateTime? DateLastImagesRefresh { get; set; }
-
- public DateTime? ItemDateModified { get; set; }
-
- public bool IsDirty { get; private set; }
-
- public void SetDateLastMetadataRefresh(DateTime? date)
- {
- if (date != DateLastMetadataRefresh)
- {
- IsDirty = true;
- }
-
- DateLastMetadataRefresh = date;
- }
-
- public void SetDateLastImagesRefresh(DateTime? date)
- {
- if (date != DateLastImagesRefresh)
- {
- IsDirty = true;
- }
-
- DateLastImagesRefresh = date;
- }
- }
-}
diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs
index fa74c5749..6659d1553 100644
--- a/MediaBrowser.Controller/Session/ISessionManager.cs
+++ b/MediaBrowser.Controller/Session/ISessionManager.cs
@@ -315,9 +315,8 @@ namespace MediaBrowser.Controller.Session
/// <summary>
/// Revokes the user tokens.
/// </summary>
- /// <param name="userId">The user identifier.</param>
/// <returns>Task.</returns>
- Task RevokeUserTokens(string userId);
+ Task RevokeUserTokens(string userId, string currentAccessToken);
/// <summary>
/// Revokes the token.
diff --git a/MediaBrowser.Controller/Subtitles/SubtitleSearchRequest.cs b/MediaBrowser.Controller/Subtitles/SubtitleSearchRequest.cs
index e781c048b..a2371426a 100644
--- a/MediaBrowser.Controller/Subtitles/SubtitleSearchRequest.cs
+++ b/MediaBrowser.Controller/Subtitles/SubtitleSearchRequest.cs
@@ -19,6 +19,7 @@ namespace MediaBrowser.Controller.Subtitles
public int? ParentIndexNumber { get; set; }
public int? ProductionYear { get; set; }
public long? RuntimeTicks { get; set; }
+ public bool IsPerfectMatch { get; set; }
public Dictionary<string, string> ProviderIds { get; set; }
public bool SearchAllProviders { get; set; }