diff options
19 files changed, 521 insertions, 105 deletions
diff --git a/MediaBrowser.Controller/Channels/ChannelAudioItem.cs b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs new file mode 100644 index 000000000..bcb2dc234 --- /dev/null +++ b/MediaBrowser.Controller/Channels/ChannelAudioItem.cs @@ -0,0 +1,102 @@ +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 MediaBrowser.Model.Users; +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 new file mode 100644 index 000000000..174cd282a --- /dev/null +++ b/MediaBrowser.Controller/Channels/ChannelFolderItem.cs @@ -0,0 +1,90 @@ +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; +using MediaBrowser.Model.Entities; + +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/ChannelVideoItem.cs b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs new file mode 100644 index 000000000..e12a84ba2 --- /dev/null +++ b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs @@ -0,0 +1,128 @@ +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Channels; +using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Users; +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/Entities/Audio/AudioPodcast.cs b/MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs new file mode 100644 index 000000000..983cc0100 --- /dev/null +++ b/MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Entities.Audio +{ + public class AudioPodcast : Audio + { + } +} diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs index cedc9591d..7b3e51cad 100644 --- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs +++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs @@ -117,6 +117,8 @@ namespace MediaBrowser.Controller.Entities public string[] PresetViews { get; set; } public SourceType[] SourceTypes { get; set; } public SourceType[] ExcludeSourceTypes { get; set; } + public TrailerType[] TrailerTypes { get; set; } + public TrailerType[] ExcludeTrailerTypes { get; set; } public InternalItemsQuery() { @@ -145,6 +147,8 @@ namespace MediaBrowser.Controller.Entities PresetViews = new string[] { }; SourceTypes = new SourceType[] { }; ExcludeSourceTypes = new SourceType[] { }; + TrailerTypes = new TrailerType[] { }; + ExcludeTrailerTypes = new TrailerType[] { }; } public InternalItemsQuery(User user) diff --git a/MediaBrowser.Controller/Entities/SourceType.cs b/MediaBrowser.Controller/Entities/SourceType.cs index 9c307b4e6..92976344c 100644 --- a/MediaBrowser.Controller/Entities/SourceType.cs +++ b/MediaBrowser.Controller/Entities/SourceType.cs @@ -3,8 +3,8 @@ namespace MediaBrowser.Controller.Entities { public enum SourceType { - Library = 0, - Channel = 1, - LiveTV = 2 + Library = 1, + Channel = 2, + LiveTV = 3 } } diff --git a/MediaBrowser.Controller/Entities/Trailer.cs b/MediaBrowser.Controller/Entities/Trailer.cs index cefc1dabe..a4ac34545 100644 --- a/MediaBrowser.Controller/Entities/Trailer.cs +++ b/MediaBrowser.Controller/Entities/Trailer.cs @@ -24,8 +24,11 @@ namespace MediaBrowser.Controller.Entities Taglines = new List<string>(); Keywords = new List<string>(); ProductionLocations = new List<string>(); + TrailerTypes = new List<TrailerType>(); } + public List<TrailerType> TrailerTypes { get; set; } + public float? Metascore { get; set; } public List<MediaUrl> RemoteTrailers { get; set; } @@ -62,20 +65,6 @@ namespace MediaBrowser.Controller.Entities /// <value>The critic rating summary.</value> public string CriticRatingSummary { get; set; } - /// <summary> - /// Gets a value indicating whether this instance is local trailer. - /// </summary> - /// <value><c>true</c> if this instance is local trailer; otherwise, <c>false</c>.</value> - [IgnoreDataMember] - public bool IsLocalTrailer - { - get - { - // Local trailers are not part of children - return GetParent() == null; - } - } - protected override string CreateUserDataKey() { var key = Movie.GetMovieUserDataKey(this); @@ -105,7 +94,7 @@ namespace MediaBrowser.Controller.Entities { var info = GetItemLookupInfo<TrailerInfo>(); - info.IsLocalTrailer = IsLocalTrailer; + info.IsLocalTrailer = TrailerTypes.Contains(TrailerType.LocalTrailer); if (!IsInMixedFolder) { diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 572f45b36..be041281f 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -75,12 +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\IChannelManager.cs" /> <Compile Include="Channels\Channel.cs" /> @@ -123,6 +126,7 @@ <Compile Include="Drawing\ImageStream.cs" /> <Compile Include="Dto\DtoOptions.cs" /> <Compile Include="Dto\IDtoService.cs" /> + <Compile Include="Entities\Audio\AudioPodcast.cs" /> <Compile Include="Entities\Audio\IHasAlbumArtist.cs" /> <Compile Include="Entities\Audio\IHasMusicGenres.cs" /> <Compile Include="Entities\Book.cs" /> diff --git a/MediaBrowser.Controller/Providers/TrailerInfo.cs b/MediaBrowser.Controller/Providers/TrailerInfo.cs index fe26ec43e..65ddc2d1e 100644 --- a/MediaBrowser.Controller/Providers/TrailerInfo.cs +++ b/MediaBrowser.Controller/Providers/TrailerInfo.cs @@ -1,3 +1,5 @@ +using MediaBrowser.Model.Entities; + namespace MediaBrowser.Controller.Providers { public class TrailerInfo : ItemLookupInfo diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 8e3284152..d9b06dcfd 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -43,6 +43,12 @@ namespace MediaBrowser.Model.Dto /// </summary> /// <value>The etag.</value> public string Etag { get; set; } + + /// <summary> + /// Gets or sets the type of the source. + /// </summary> + /// <value>The type of the source.</value> + public string SourceType { get; set; } /// <summary> /// Gets or sets the playlist item identifier. diff --git a/MediaBrowser.Model/Entities/TrailerType.cs b/MediaBrowser.Model/Entities/TrailerType.cs index c96a05bcd..085f461cf 100644 --- a/MediaBrowser.Model/Entities/TrailerType.cs +++ b/MediaBrowser.Model/Entities/TrailerType.cs @@ -5,6 +5,7 @@ namespace MediaBrowser.Model.Entities ComingSoonToTheaters = 1, ComingSoonToDvd = 2, ComingSoonToStreaming = 3, - Archive = 4 + Archive = 4, + LocalTrailer = 5 } }
\ No newline at end of file diff --git a/MediaBrowser.Providers/Movies/MovieMetadataService.cs b/MediaBrowser.Providers/Movies/MovieMetadataService.cs index 1e55dce76..e70ec0057 100644 --- a/MediaBrowser.Providers/Movies/MovieMetadataService.cs +++ b/MediaBrowser.Providers/Movies/MovieMetadataService.cs @@ -67,6 +67,11 @@ namespace MediaBrowser.Providers.Movies protected override void MergeData(MetadataResult<Trailer> source, MetadataResult<Trailer> target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings) { ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings); + + if (replaceData || target.Item.TrailerTypes.Count == 0) + { + target.Item.TrailerTypes = source.Item.TrailerTypes; + } } } diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs index ee49a7005..e957b9889 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs +++ b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs @@ -424,6 +424,7 @@ namespace MediaBrowser.Server.Implementations.Channels var parentFolderId = parentFolder.Id; var id = GetInternalChannelId(channelInfo.Name); + var idString = id.ToString("N"); var path = Channel.GetInternalMetadataPath(_config.ApplicationPaths.InternalMetadataPath, id); @@ -431,7 +432,6 @@ namespace MediaBrowser.Server.Implementations.Channels var forceUpdate = false; var item = _libraryManager.GetItemById(id) as Channel; - var channelId = channelInfo.Name.GetMD5().ToString("N"); if (item == null) { @@ -452,11 +452,11 @@ namespace MediaBrowser.Server.Implementations.Channels } item.Path = path; - if (!string.Equals(item.ChannelId, channelId, StringComparison.OrdinalIgnoreCase)) + if (!string.Equals(item.ChannelId, idString, StringComparison.OrdinalIgnoreCase)) { forceUpdate = true; } - item.ChannelId = channelId; + item.ChannelId = idString; if (item.ParentId != parentFolderId) { @@ -505,7 +505,7 @@ namespace MediaBrowser.Server.Implementations.Channels public Channel GetChannel(string id) { - return _libraryManager.GetItemById(new Guid(id)) as Channel; + return _libraryManager.GetItemById(id) as Channel; } public IEnumerable<ChannelFeatures> GetAllChannelFeatures() @@ -523,6 +523,11 @@ namespace MediaBrowser.Server.Implementations.Channels public ChannelFeatures GetChannelFeatures(string id) { + if (string.IsNullOrWhiteSpace(id)) + { + throw new ArgumentNullException("id"); + } + var channel = GetChannel(id); var channelProvider = GetChannelProvider(channel); @@ -1261,7 +1266,14 @@ namespace MediaBrowser.Server.Implementations.Channels } else if (info.MediaType == ChannelMediaType.Audio) { - item = GetItemById<Audio>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew); + if (info.ContentType == ChannelMediaContentType.Podcast) + { + item = GetItemById<AudioPodcast>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew); + } + else + { + item = GetItemById<Audio>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew); + } } else { @@ -1302,6 +1314,16 @@ namespace MediaBrowser.Server.Implementations.Channels item.Tags = info.Tags; } + var trailer = item as Trailer; + if (trailer != null) + { + if (!info.TrailerTypes.SequenceEqual(trailer.TrailerTypes)) + { + forceUpdate = true; + } + trailer.TrailerTypes = info.TrailerTypes; + } + item.ChannelId = internalChannelId.ToString("N"); if (item.ParentId != internalChannelId) @@ -1384,7 +1406,12 @@ namespace MediaBrowser.Server.Implementations.Channels internal IChannel GetChannelProvider(Channel channel) { - var result = GetAllChannels().FirstOrDefault(i => string.Equals(i.Name.GetMD5().ToString("N"), channel.ChannelId, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, channel.Name, StringComparison.OrdinalIgnoreCase)); + if (channel == null) + { + throw new ArgumentNullException("channel"); + } + + var result = GetAllChannels().FirstOrDefault(i => string.Equals(GetInternalChannelId(i.Name).ToString("N"), channel.ChannelId, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Name, channel.Name, StringComparison.OrdinalIgnoreCase)); if (result == null) { @@ -1519,7 +1546,6 @@ namespace MediaBrowser.Server.Implementations.Channels Progress = new Progress<double>() }; - var host = new Uri(source.Path).Host.ToLower(); var channel = GetChannel(item.ChannelId); var channelProvider = GetChannelProvider(channel); var features = channelProvider.GetChannelFeatures(); diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 581b03f08..3b63eccfc 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -316,6 +316,11 @@ namespace MediaBrowser.Server.Implementations.Dto ServerId = _appHost.SystemId }; + if (item.SourceType == SourceType.Channel) + { + dto.SourceType = item.SourceType.ToString(); + } + if (fields.Contains(ItemFields.People)) { AttachPeople(dto, item); diff --git a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs index 5b72860b6..5adddd38a 100644 --- a/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs +++ b/MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs @@ -24,17 +24,15 @@ namespace MediaBrowser.Server.Implementations.Intros public class DefaultIntroProvider : IIntroProvider { private readonly ISecurityManager _security; - private readonly IChannelManager _channelManager; private readonly ILocalizationManager _localization; private readonly IConfigurationManager _serverConfig; private readonly ILibraryManager _libraryManager; private readonly IFileSystem _fileSystem; private readonly IMediaSourceManager _mediaSourceManager; - public DefaultIntroProvider(ISecurityManager security, IChannelManager channelManager, ILocalizationManager localization, IConfigurationManager serverConfig, ILibraryManager libraryManager, IFileSystem fileSystem, IMediaSourceManager mediaSourceManager) + public DefaultIntroProvider(ISecurityManager security, ILocalizationManager localization, IConfigurationManager serverConfig, ILibraryManager libraryManager, IFileSystem fileSystem, IMediaSourceManager mediaSourceManager) { _security = security; - _channelManager = channelManager; _localization = localization; _serverConfig = serverConfig; _libraryManager = libraryManager; @@ -79,76 +77,45 @@ namespace MediaBrowser.Server.Implementations.Intros AppearsInItemId = item.Id }); - if (config.EnableIntrosFromMoviesInLibrary) - { - var inputItems = _libraryManager.GetItems(new InternalItemsQuery(user) - { - IncludeItemTypes = new[] { typeof(Movie).Name } - - }, new string[] { }); - - var itemsWithTrailers = inputItems - .Where(i => - { - var hasTrailers = i as IHasTrailers; - - if (hasTrailers != null && hasTrailers.LocalTrailerIds.Count > 0) - { - if (i is Movie) - { - return !IsDuplicate(item, i); - } - } - return false; - }); - - candidates.AddRange(itemsWithTrailers.Select(i => new ItemWithTrailer - { - Item = i, - Type = ItemWithTrailerType.ItemWithTrailer, - User = user, - WatchingItem = item, - WatchingItemPeople = itemPeople, - AllPeople = allPeople, - Random = random, - LibraryManager = _libraryManager - })); - } - var trailerTypes = new List<TrailerType>(); - if (config.EnableIntrosFromUpcomingTrailers) - { - trailerTypes.Add(TrailerType.ComingSoonToTheaters); - } - if (config.EnableIntrosFromUpcomingDvdMovies) - { - trailerTypes.Add(TrailerType.ComingSoonToDvd); - } - if (config.EnableIntrosFromUpcomingStreamingMovies) + if (config.EnableIntrosFromMoviesInLibrary) { - trailerTypes.Add(TrailerType.ComingSoonToStreaming); + trailerTypes.Add(TrailerType.LocalTrailer); } - if (config.EnableIntrosFromSimilarMovies) + + if (IsSupporter) { - trailerTypes.Add(TrailerType.Archive); + if (config.EnableIntrosFromUpcomingTrailers) + { + trailerTypes.Add(TrailerType.ComingSoonToTheaters); + } + if (config.EnableIntrosFromUpcomingDvdMovies) + { + trailerTypes.Add(TrailerType.ComingSoonToDvd); + } + if (config.EnableIntrosFromUpcomingStreamingMovies) + { + trailerTypes.Add(TrailerType.ComingSoonToStreaming); + } + if (config.EnableIntrosFromSimilarMovies) + { + trailerTypes.Add(TrailerType.Archive); + } } - if (trailerTypes.Count > 0 && IsSupporter) + if (trailerTypes.Count > 0) { - var channelTrailers = await _channelManager.GetAllMediaInternal(new AllChannelMediaQuery + var trailerResult = _libraryManager.GetItems(new InternalItemsQuery { - ContentTypes = new[] { ChannelMediaContentType.MovieExtra }, - ExtraTypes = new[] { ExtraType.Trailer }, - UserId = user.Id.ToString("N"), + IncludeItemTypes = new[] { typeof(Trailer).Name }, TrailerTypes = trailerTypes.ToArray() + }); - }, CancellationToken.None); - - candidates.AddRange(channelTrailers.Items.Select(i => new ItemWithTrailer + candidates.AddRange(trailerResult.Items.Select(i => new ItemWithTrailer { Item = i, - Type = ItemWithTrailerType.ChannelTrailer, + Type = i.SourceType == SourceType.Channel ? ItemWithTrailerType.ChannelTrailer : ItemWithTrailerType.ItemWithTrailer, User = user, WatchingItem = item, WatchingItemPeople = itemPeople, @@ -156,7 +123,7 @@ namespace MediaBrowser.Server.Implementations.Intros Random = random, LibraryManager = _libraryManager })); - } + } return GetResult(item, candidates, config, ratingLevel); } @@ -556,7 +523,6 @@ namespace MediaBrowser.Server.Implementations.Intros internal enum ItemWithTrailerType { - LibraryTrailer, ChannelTrailer, ItemWithTrailer } diff --git a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs index 184737ece..19b66836b 100644 --- a/MediaBrowser.Server.Implementations/Library/LibraryManager.cs +++ b/MediaBrowser.Server.Implementations/Library/LibraryManager.cs @@ -40,8 +40,10 @@ using CommonIO; using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Library; using MediaBrowser.Model.Net; +using MediaBrowser.Server.Implementations.Library.Resolvers; using MoreLinq; using SortOrder = MediaBrowser.Model.Entities.SortOrder; +using VideoResolver = MediaBrowser.Naming.Video.VideoResolver; namespace MediaBrowser.Server.Implementations.Library { @@ -454,10 +456,11 @@ namespace MediaBrowser.Server.Implementations.Library /// Resolves the item. /// </summary> /// <param name="args">The args.</param> + /// <param name="resolvers">The resolvers.</param> /// <returns>BaseItem.</returns> - private BaseItem ResolveItem(ItemResolveArgs args) + private BaseItem ResolveItem(ItemResolveArgs args, IItemResolver[] resolvers) { - var item = EntityResolvers.Select(r => Resolve(args, r)) + var item = (resolvers ?? EntityResolvers).Select(r => Resolve(args, r)) .FirstOrDefault(i => i != null); if (item != null) @@ -556,10 +559,10 @@ namespace MediaBrowser.Server.Implementations.Library public BaseItem ResolvePath(FileSystemMetadata fileInfo, Folder parent = null) { - return ResolvePath(fileInfo, new DirectoryService(_logger, _fileSystem), parent); + return ResolvePath(fileInfo, new DirectoryService(_logger, _fileSystem), null, parent); } - private BaseItem ResolvePath(FileSystemMetadata fileInfo, IDirectoryService directoryService, Folder parent = null, string collectionType = null) + private BaseItem ResolvePath(FileSystemMetadata fileInfo, IDirectoryService directoryService, IItemResolver[] resolvers, Folder parent = null, string collectionType = null) { if (fileInfo == null) { @@ -615,7 +618,7 @@ namespace MediaBrowser.Server.Implementations.Library return null; } - return ResolveItem(args); + return ResolveItem(args, resolvers); } public bool IgnoreFile(FileSystemMetadata file, BaseItem parent) @@ -658,11 +661,18 @@ namespace MediaBrowser.Server.Implementations.Library public IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files, IDirectoryService directoryService, Folder parent, string collectionType) { + return ResolvePaths(files, directoryService, parent, collectionType, EntityResolvers); + } + + public IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files, IDirectoryService directoryService, Folder parent, string collectionType, IItemResolver[] resolvers) + { var fileList = files.Where(i => !IgnoreFile(i, parent)).ToList(); if (parent != null) { - foreach (var resolver in MultiItemResolvers) + var multiItemResolvers = resolvers == null ? MultiItemResolvers : resolvers.OfType<IMultiItemResolver>().ToArray(); + + foreach (var resolver in multiItemResolvers) { var result = resolver.ResolveMultiple(parent, fileList, collectionType, directoryService); @@ -675,22 +685,22 @@ namespace MediaBrowser.Server.Implementations.Library { ResolverHelper.SetInitialItemValues(item, parent, _fileSystem, this, directoryService); } - items.AddRange(ResolveFileList(result.ExtraFiles, directoryService, parent, collectionType)); + items.AddRange(ResolveFileList(result.ExtraFiles, directoryService, parent, collectionType, resolvers)); return items; } } } - return ResolveFileList(fileList, directoryService, parent, collectionType); + return ResolveFileList(fileList, directoryService, parent, collectionType, resolvers); } - private IEnumerable<BaseItem> ResolveFileList(IEnumerable<FileSystemMetadata> fileList, IDirectoryService directoryService, Folder parent, string collectionType) + private IEnumerable<BaseItem> ResolveFileList(IEnumerable<FileSystemMetadata> fileList, IDirectoryService directoryService, Folder parent, string collectionType, IItemResolver[] resolvers) { return fileList.Select(f => { try { - return ResolvePath(f, directoryService, parent, collectionType); + return ResolvePath(f, directoryService, resolvers, parent, collectionType); } catch (Exception ex) { @@ -2306,12 +2316,17 @@ namespace MediaBrowser.Server.Implementations.Library files.AddRange(currentVideo.Extras.Where(i => string.Equals(i.ExtraType, "trailer", StringComparison.OrdinalIgnoreCase)).Select(i => _fileSystem.GetFileInfo(i.Path))); } - return ResolvePaths(files, directoryService, null, null) - .OfType<Video>() + var resolvers = new IItemResolver[] + { + new GenericVideoResolver<Trailer>(this) + }; + + return ResolvePaths(files, directoryService, null, null, resolvers) + .OfType<Trailer>() .Select(video => { // Try to retrieve it from the db. If we don't find it, use the resolved version - var dbItem = GetItemById(video.Id) as Video; + var dbItem = GetItemById(video.Id) as Trailer; if (dbItem != null) { diff --git a/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs b/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs index e776e58f9..10263f7d7 100644 --- a/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs +++ b/MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs @@ -31,7 +31,10 @@ namespace MediaBrowser.Server.Implementations.Library var trailerResult = _libraryManager.GetItems(new InternalItemsQuery { IncludeItemTypes = new[] { typeof(Trailer).Name }, - //IsLocalTrailer = false + ExcludeTrailerTypes = new[] + { + TrailerType.LocalTrailer + } }); var trailers = trailerResult.Items; diff --git a/MediaBrowser.Server.Implementations/Library/Resolvers/VideoResolver.cs b/MediaBrowser.Server.Implementations/Library/Resolvers/VideoResolver.cs index 97682db66..c7f21cef1 100644 --- a/MediaBrowser.Server.Implementations/Library/Resolvers/VideoResolver.cs +++ b/MediaBrowser.Server.Implementations/Library/Resolvers/VideoResolver.cs @@ -34,4 +34,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers get { return ResolverPriority.Last; } } } + + public class GenericVideoResolver<T> : BaseVideoResolver<T> + where T : Video, new () + { + public GenericVideoResolver(ILibraryManager libraryManager) : base(libraryManager) + { + } + } } diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs index c224c45d5..3f50278f6 100644 --- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs +++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs @@ -224,6 +224,7 @@ namespace MediaBrowser.Server.Implementations.Persistence _connection.AddColumn(Logger, "TypedBaseItems", "TopParentId", "Text"); _connection.AddColumn(Logger, "TypedBaseItems", "IsItemByName", "BIT"); _connection.AddColumn(Logger, "TypedBaseItems", "SourceType", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "TrailerTypes", "Text"); PrepareStatements(); @@ -355,7 +356,8 @@ namespace MediaBrowser.Server.Implementations.Persistence "LockedFields", "Studios", "Tags", - "SourceType" + "SourceType", + "TrailerTypes" }; private readonly string[] _mediaStreamSaveColumns = @@ -456,7 +458,8 @@ namespace MediaBrowser.Server.Implementations.Persistence "UnratedType", "TopParentId", "IsItemByName", - "SourceType" + "SourceType", + "TrailerTypes" }; _saveItemCommand = _connection.CreateCommand(); _saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; @@ -751,7 +754,17 @@ namespace MediaBrowser.Server.Implementations.Persistence _saveItemCommand.GetParameter(index++).Value = isByName; _saveItemCommand.GetParameter(index++).Value = item.SourceType.ToString(); - + + var trailer = item as Trailer; + if (trailer != null) + { + _saveItemCommand.GetParameter(index++).Value = string.Join("|", trailer.TrailerTypes.Select(i => i.ToString()).ToArray()); + } + else + { + _saveItemCommand.GetParameter(index++).Value = null; + } + _saveItemCommand.Transaction = transaction; _saveItemCommand.ExecuteNonQuery(); @@ -1119,6 +1132,15 @@ namespace MediaBrowser.Server.Implementations.Persistence item.SourceType = (SourceType)Enum.Parse(typeof(SourceType), reader.GetString(49), true); } + var trailer = item as Trailer; + if (trailer != null) + { + if (!reader.IsDBNull(50)) + { + trailer.TrailerTypes = reader.GetString(50).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).Select(i => (TrailerType)Enum.Parse(typeof(TrailerType), i, true)).ToList(); + } + } + return item; } @@ -1902,6 +1924,34 @@ namespace MediaBrowser.Server.Implementations.Persistence var inClause = string.Join(",", query.ExcludeSourceTypes.Select(i => "'" + i + "'").ToArray()); whereClauses.Add(string.Format("SourceType not in ({0})", inClause)); } + + if (query.TrailerTypes.Length > 0) + { + var clauses = new List<string>(); + var index = 0; + foreach (var type in query.TrailerTypes) + { + clauses.Add("TrailerTypes like @TrailerTypes" + index); + cmd.Parameters.Add(cmd, "@TrailerTypes" + index, DbType.String).Value = "%" + type + "%"; + index++; + } + var clause = "(" + string.Join(" OR ", clauses.ToArray()) + ")"; + whereClauses.Add(clause); + } + + if (query.ExcludeTrailerTypes.Length > 0) + { + var clauses = new List<string>(); + var index = 0; + foreach (var type in query.ExcludeTrailerTypes) + { + clauses.Add("TrailerTypes not like @TrailerTypes" + index); + cmd.Parameters.Add(cmd, "@TrailerTypes" + index, DbType.String).Value = "%" + type + "%"; + index++; + } + var clause = "(" + string.Join(" AND ", clauses.ToArray()) + ")"; + whereClauses.Add(clause); + } if (query.IsAiring.HasValue) { |
