Browse Source

Merge pull request #1563 from MediaBrowser/dev

Dev
Luke 9 years ago
parent
commit
3ab212d070
82 changed files with 860 additions and 531 deletions
  1. 4 7
      MediaBrowser.Api/Library/LibraryService.cs
  2. 21 38
      MediaBrowser.Api/Movies/MoviesService.cs
  3. 3 13
      MediaBrowser.Api/Movies/TrailersService.cs
  4. 15 0
      MediaBrowser.Controller/Channels/Channel.cs
  5. 1 1
      MediaBrowser.Controller/Channels/ChannelAudioItem.cs
  6. 1 1
      MediaBrowser.Controller/Channels/ChannelFolderItem.cs
  7. 2 16
      MediaBrowser.Controller/Channels/ChannelVideoItem.cs
  8. 0 11
      MediaBrowser.Controller/Channels/IChannelItem.cs
  9. 2 2
      MediaBrowser.Controller/Channels/IChannelManager.cs
  10. 0 18
      MediaBrowser.Controller/Channels/IChannelMediaItem.cs
  11. 35 1
      MediaBrowser.Controller/Entities/Audio/Audio.cs
  12. 12 0
      MediaBrowser.Controller/Entities/Audio/AudioPodcast.cs
  13. 45 0
      MediaBrowser.Controller/Entities/BaseItem.cs
  14. 30 2
      MediaBrowser.Controller/Entities/Folder.cs
  15. 8 0
      MediaBrowser.Controller/Entities/InternalItemsQuery.cs
  16. 10 0
      MediaBrowser.Controller/Entities/SourceType.cs
  17. 45 15
      MediaBrowser.Controller/Entities/Trailer.cs
  18. 60 0
      MediaBrowser.Controller/Entities/Video.cs
  19. 7 0
      MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs
  20. 7 0
      MediaBrowser.Controller/LiveTv/LiveTvChannel.cs
  21. 7 0
      MediaBrowser.Controller/LiveTv/LiveTvProgram.cs
  22. 7 0
      MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs
  23. 9 1
      MediaBrowser.Controller/LiveTv/RecordingGroup.cs
  24. 4 5
      MediaBrowser.Controller/MediaBrowser.Controller.csproj
  25. 0 11
      MediaBrowser.Controller/Providers/ChannelItemLookupInfo.cs
  26. 2 0
      MediaBrowser.Controller/Providers/TrailerInfo.cs
  27. 1 1
      MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs
  28. 4 4
      MediaBrowser.Dlna/Profiles/DefaultProfile.cs
  29. 42 0
      MediaBrowser.Dlna/Profiles/KodiProfile.cs
  30. 4 4
      MediaBrowser.Dlna/Profiles/Xml/BubbleUPnp.xml
  31. 4 4
      MediaBrowser.Dlna/Profiles/Xml/Default.xml
  32. 4 4
      MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml
  33. 4 4
      MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml
  34. 4 4
      MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml
  35. 6 0
      MediaBrowser.Dlna/Profiles/Xml/Kodi.xml
  36. 4 4
      MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml
  37. 4 4
      MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml
  38. 4 4
      MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml
  39. 4 4
      MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml
  40. 4 4
      MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml
  41. 4 4
      MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml
  42. 4 4
      MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml
  43. 4 4
      MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml
  44. 4 4
      MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml
  45. 4 4
      MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml
  46. 4 4
      MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml
  47. 4 4
      MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml
  48. 4 4
      MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2014).xml
  49. 4 4
      MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml
  50. 4 4
      MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 4.xml
  51. 4 4
      MediaBrowser.Dlna/Profiles/Xml/Vlc.xml
  52. 4 4
      MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml
  53. 4 4
      MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml
  54. 4 4
      MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml
  55. 4 4
      MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml
  56. 4 4
      MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
  57. 6 0
      MediaBrowser.Model/Dto/BaseItemDto.cs
  58. 2 1
      MediaBrowser.Model/Entities/TrailerType.cs
  59. 0 25
      MediaBrowser.Providers/Channels/AudioChannelItemMetadataService.cs
  60. 0 25
      MediaBrowser.Providers/Channels/VideoChannelItemMetadataService.cs
  61. 0 2
      MediaBrowser.Providers/MediaBrowser.Providers.csproj
  62. 1 18
      MediaBrowser.Providers/Movies/MovieDbImageProvider.cs
  63. 3 18
      MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs
  64. 3 17
      MediaBrowser.Providers/Movies/MovieExternalIds.cs
  65. 34 2
      MediaBrowser.Providers/Movies/MovieMetadataService.cs
  66. 1 18
      MediaBrowser.Providers/Omdb/OmdbImageProvider.cs
  67. 4 14
      MediaBrowser.Providers/Omdb/OmdbItemProvider.cs
  68. 3 3
      MediaBrowser.Server.Implementations/Channels/ChannelDynamicMediaSourceProvider.cs
  69. 104 28
      MediaBrowser.Server.Implementations/Channels/ChannelManager.cs
  70. 15 10
      MediaBrowser.Server.Implementations/Dto/DtoService.cs
  71. 2 2
      MediaBrowser.Server.Implementations/EntryPoints/ActivityLogEntryPoint.cs
  72. 1 1
      MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs
  73. 1 1
      MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs
  74. 28 62
      MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs
  75. 29 18
      MediaBrowser.Server.Implementations/Library/LibraryManager.cs
  76. 9 5
      MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs
  77. 8 0
      MediaBrowser.Server.Implementations/Library/Resolvers/VideoResolver.cs
  78. 8 3
      MediaBrowser.Server.Implementations/Library/UserViewManager.cs
  79. 1 1
      MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs
  80. 84 5
      MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
  81. 1 1
      MediaBrowser.Server.Implementations/Sync/SyncManager.cs
  82. 18 0
      MediaBrowser.Server.Mac/Emby.Server.Mac.csproj

+ 4 - 7
MediaBrowser.Api/Library/LibraryService.cs

@@ -289,7 +289,6 @@ namespace MediaBrowser.Api.Library
         private readonly IActivityManager _activityManager;
         private readonly IActivityManager _activityManager;
         private readonly ILocalizationManager _localization;
         private readonly ILocalizationManager _localization;
         private readonly ILiveTvManager _liveTv;
         private readonly ILiveTvManager _liveTv;
-        private readonly IChannelManager _channelManager;
         private readonly ITVSeriesManager _tvManager;
         private readonly ITVSeriesManager _tvManager;
         private readonly ILibraryMonitor _libraryMonitor;
         private readonly ILibraryMonitor _libraryMonitor;
         private readonly IFileSystem _fileSystem;
         private readonly IFileSystem _fileSystem;
@@ -298,7 +297,7 @@ namespace MediaBrowser.Api.Library
         /// Initializes a new instance of the <see cref="LibraryService" /> class.
         /// Initializes a new instance of the <see cref="LibraryService" /> class.
         /// </summary>
         /// </summary>
         public LibraryService(IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager,
         public LibraryService(IItemRepository itemRepo, ILibraryManager libraryManager, IUserManager userManager,
-                              IDtoService dtoService, IUserDataManager userDataManager, IAuthorizationContext authContext, IActivityManager activityManager, ILocalizationManager localization, ILiveTvManager liveTv, IChannelManager channelManager, ITVSeriesManager tvManager, ILibraryMonitor libraryMonitor, IFileSystem fileSystem)
+                              IDtoService dtoService, IUserDataManager userDataManager, IAuthorizationContext authContext, IActivityManager activityManager, ILocalizationManager localization, ILiveTvManager liveTv, ITVSeriesManager tvManager, ILibraryMonitor libraryMonitor, IFileSystem fileSystem)
         {
         {
             _itemRepo = itemRepo;
             _itemRepo = itemRepo;
             _libraryManager = libraryManager;
             _libraryManager = libraryManager;
@@ -309,7 +308,6 @@ namespace MediaBrowser.Api.Library
             _activityManager = activityManager;
             _activityManager = activityManager;
             _localization = localization;
             _localization = localization;
             _liveTv = liveTv;
             _liveTv = liveTv;
-            _channelManager = channelManager;
             _tvManager = tvManager;
             _tvManager = tvManager;
             _libraryMonitor = libraryMonitor;
             _libraryMonitor = libraryMonitor;
             _fileSystem = fileSystem;
             _fileSystem = fileSystem;
@@ -379,11 +377,10 @@ namespace MediaBrowser.Api.Library
             }
             }
 
 
             var program = item as IHasProgramAttributes;
             var program = item as IHasProgramAttributes;
-            var channelItem = item as ChannelVideoItem;
 
 
-            if (item is Movie || (program != null && program.IsMovie) || (channelItem != null && channelItem.ContentType == ChannelMediaContentType.Movie) || (channelItem != null && channelItem.ContentType == ChannelMediaContentType.MovieExtra))
+            if (item is Movie || (program != null && program.IsMovie) || item is Trailer)
             {
             {
-                return new MoviesService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService, _channelManager)
+                return new MoviesService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService)
                 {
                 {
                     AuthorizationContext = AuthorizationContext,
                     AuthorizationContext = AuthorizationContext,
                     Logger = Logger,
                     Logger = Logger,
@@ -400,7 +397,7 @@ namespace MediaBrowser.Api.Library
                 });
                 });
             }
             }
 
 
-            if (item is Series || (program != null && program.IsSeries) || (channelItem != null && channelItem.ContentType == ChannelMediaContentType.Episode))
+            if (item is Series || (program != null && program.IsSeries) )
             {
             {
                 return new TvShowsService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService, _tvManager)
                 return new TvShowsService(_userManager, _userDataManager, _libraryManager, _itemRepo, _dtoService, _tvManager)
                 {
                 {

+ 21 - 38
MediaBrowser.Api/Movies/MoviesService.cs

@@ -91,22 +91,21 @@ namespace MediaBrowser.Api.Movies
         private readonly IItemRepository _itemRepo;
         private readonly IItemRepository _itemRepo;
         private readonly IDtoService _dtoService;
         private readonly IDtoService _dtoService;
 
 
-        private readonly IChannelManager _channelManager;
-
         /// <summary>
         /// <summary>
-        /// Initializes a new instance of the <see cref="MoviesService"/> class.
+        /// Initializes a new instance of the <see cref="MoviesService" /> class.
         /// </summary>
         /// </summary>
         /// <param name="userManager">The user manager.</param>
         /// <param name="userManager">The user manager.</param>
         /// <param name="userDataRepository">The user data repository.</param>
         /// <param name="userDataRepository">The user data repository.</param>
         /// <param name="libraryManager">The library manager.</param>
         /// <param name="libraryManager">The library manager.</param>
-        public MoviesService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IItemRepository itemRepo, IDtoService dtoService, IChannelManager channelManager)
+        /// <param name="itemRepo">The item repo.</param>
+        /// <param name="dtoService">The dto service.</param>
+        public MoviesService(IUserManager userManager, IUserDataManager userDataRepository, ILibraryManager libraryManager, IItemRepository itemRepo, IDtoService dtoService)
         {
         {
             _userManager = userManager;
             _userManager = userManager;
             _userDataRepository = userDataRepository;
             _userDataRepository = userDataRepository;
             _libraryManager = libraryManager;
             _libraryManager = libraryManager;
             _itemRepo = itemRepo;
             _itemRepo = itemRepo;
             _dtoService = dtoService;
             _dtoService = dtoService;
-            _channelManager = channelManager;
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -138,6 +137,14 @@ namespace MediaBrowser.Api.Movies
             {
             {
                 IncludeItemTypes = new[] { typeof(Movie).Name }
                 IncludeItemTypes = new[] { typeof(Movie).Name }
             };
             };
+
+            if (user.Configuration.IncludeTrailersInSuggestions)
+            {
+                var includeList = query.IncludeItemTypes.ToList();
+                includeList.Add(typeof(Trailer).Name);
+                query.IncludeItemTypes = includeList.ToArray();
+            }
+
             var parentIds = string.IsNullOrWhiteSpace(request.ParentId) ? new string[] { } : new[] { request.ParentId };
             var parentIds = string.IsNullOrWhiteSpace(request.ParentId) ? new string[] { } : new[] { request.ParentId };
             var movies = _libraryManager.GetItems(query, parentIds);
             var movies = _libraryManager.GetItems(query, parentIds);
             movies = _libraryManager.ReplaceVideosWithPrimaryVersions(movies);
             movies = _libraryManager.ReplaceVideosWithPrimaryVersions(movies);
@@ -150,19 +157,6 @@ namespace MediaBrowser.Api.Movies
             listEligibleForCategories.AddRange(list);
             listEligibleForCategories.AddRange(list);
             listEligibleForSuggestion.AddRange(list);
             listEligibleForSuggestion.AddRange(list);
 
 
-            if (user.Configuration.IncludeTrailersInSuggestions)
-            {
-                var trailerResult = await _channelManager.GetAllMediaInternal(new AllChannelMediaQuery
-                {
-                    ContentTypes = new[] { ChannelMediaContentType.MovieExtra },
-                    ExtraTypes = new[] { ExtraType.Trailer },
-                    UserId = user.Id.ToString("N")
-
-                }, CancellationToken.None).ConfigureAwait(false);
-
-                listEligibleForSuggestion.AddRange(trailerResult.Items);
-            }
-
             listEligibleForCategories = listEligibleForCategories
             listEligibleForCategories = listEligibleForCategories
                 .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
                 .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
                 .DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString(), StringComparer.OrdinalIgnoreCase)
                 .DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString(), StringComparer.OrdinalIgnoreCase)
@@ -194,6 +188,14 @@ namespace MediaBrowser.Api.Movies
             {
             {
                 IncludeItemTypes = new[] { typeof(Movie).Name }
                 IncludeItemTypes = new[] { typeof(Movie).Name }
             };
             };
+
+            if (user == null || user.Configuration.IncludeTrailersInSuggestions)
+            {
+                var includeList = query.IncludeItemTypes.ToList();
+                includeList.Add(typeof(Trailer).Name);
+                query.IncludeItemTypes = includeList.ToArray();
+            }
+
             var parentIds = new string[] { };
             var parentIds = new string[] { };
             var list = _libraryManager.GetItems(query, parentIds)
             var list = _libraryManager.GetItems(query, parentIds)
                 .Where(i =>
                 .Where(i =>
@@ -202,28 +204,9 @@ namespace MediaBrowser.Api.Movies
                     var v = i as Video;
                     var v = i as Video;
                     return v != null && !v.PrimaryVersionId.HasValue;
                     return v != null && !v.PrimaryVersionId.HasValue;
                 })
                 })
+                .DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString("N"))
                 .ToList();
                 .ToList();
 
 
-            if (user != null && user.Configuration.IncludeTrailersInSuggestions)
-            {
-                var trailerResult = await _channelManager.GetAllMediaInternal(new AllChannelMediaQuery
-                {
-                    ContentTypes = new[] { ChannelMediaContentType.MovieExtra },
-                    ExtraTypes = new[] { ExtraType.Trailer },
-                    UserId = user.Id.ToString("N")
-
-                }, CancellationToken.None).ConfigureAwait(false);
-
-                var newTrailers = trailerResult.Items;
-
-                list.AddRange(newTrailers);
-
-                list = list
-                    .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase)
-                    .DistinctBy(i => i.GetProviderId(MetadataProviders.Imdb) ?? Guid.NewGuid().ToString(), StringComparer.OrdinalIgnoreCase)
-                    .ToList();
-            }
-
             if (item is Video)
             if (item is Video)
             {
             {
                 var imdbId = item.GetProviderId(MetadataProviders.Imdb);
                 var imdbId = item.GetProviderId(MetadataProviders.Imdb);

+ 3 - 13
MediaBrowser.Api/Movies/TrailersService.cs

@@ -108,20 +108,10 @@ namespace MediaBrowser.Api.Movies
 
 
         private async Task<QueryResult<BaseItem>> GetAllTrailers(User user)
         private async Task<QueryResult<BaseItem>> GetAllTrailers(User user)
         {
         {
-            var trailerResult = await _channelManager.GetAllMediaInternal(new AllChannelMediaQuery
+            return _libraryManager.GetItems(new InternalItemsQuery(user)
             {
             {
-                ContentTypes = new[] { ChannelMediaContentType.MovieExtra },
-                ExtraTypes = new[] { ExtraType.Trailer },
-                UserId = user.Id.ToString("N")
-
-            }, CancellationToken.None).ConfigureAwait(false);
-
-
-            return new QueryResult<BaseItem>
-            {
-                Items = trailerResult.Items,
-                TotalRecordCount = trailerResult.TotalRecordCount
-            };
+                IncludeItemTypes = new[] {typeof (Trailer).Name}
+            });
         }
         }
     }
     }
 }
 }

+ 15 - 0
MediaBrowser.Controller/Channels/Channel.cs

@@ -3,6 +3,7 @@ using MediaBrowser.Model.Channels;
 using MediaBrowser.Model.Querying;
 using MediaBrowser.Model.Querying;
 using System;
 using System;
 using System.Linq;
 using System.Linq;
+using System.Runtime.Serialization;
 using System.Threading;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 
 
@@ -30,6 +31,13 @@ namespace MediaBrowser.Controller.Channels
             return base.IsVisible(user);
             return base.IsVisible(user);
         }
         }
 
 
+        [IgnoreDataMember]
+        public override SourceType SourceType
+        {
+            get { return SourceType.Channel; }
+            set { }
+        }
+
         public override async Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
         public override async Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
         {
         {
             try
             try
@@ -75,5 +83,12 @@ namespace MediaBrowser.Controller.Channels
         {
         {
             return false;
             return false;
         }
         }
+
+        internal static bool IsChannelVisible(BaseItem channelItem, User user)
+        {
+            var channel = ChannelManager.GetChannel(channelItem.ChannelId);
+
+            return channel.IsVisible(user);
+        }
     }
     }
 }
 }

+ 1 - 1
MediaBrowser.Controller/Channels/ChannelAudioItem.cs

@@ -12,7 +12,7 @@ using System.Threading;
 
 
 namespace MediaBrowser.Controller.Channels
 namespace MediaBrowser.Controller.Channels
 {
 {
-    public class ChannelAudioItem : Audio, IChannelMediaItem
+    public class ChannelAudioItem : Audio
     {
     {
         public ChannelMediaContentType ContentType { get; set; }
         public ChannelMediaContentType ContentType { get; set; }
 
 

+ 1 - 1
MediaBrowser.Controller/Channels/ChannelFolderItem.cs

@@ -11,7 +11,7 @@ using MediaBrowser.Model.Entities;
 
 
 namespace MediaBrowser.Controller.Channels
 namespace MediaBrowser.Controller.Channels
 {
 {
-    public class ChannelFolderItem : Folder, IChannelItem
+    public class ChannelFolderItem : Folder
     {
     {
         public ChannelFolderType ChannelFolderType { get; set; }
         public ChannelFolderType ChannelFolderType { get; set; }
 
 

+ 2 - 16
MediaBrowser.Controller/Channels/ChannelVideoItem.cs

@@ -13,7 +13,7 @@ using System.Threading;
 
 
 namespace MediaBrowser.Controller.Channels
 namespace MediaBrowser.Controller.Channels
 {
 {
-    public class ChannelVideoItem : Video, IChannelMediaItem, IHasLookupInfo<ChannelItemLookupInfo>
+    public class ChannelVideoItem : Video
     {
     {
         public ChannelMediaContentType ContentType { get; set; }
         public ChannelMediaContentType ContentType { get; set; }
 
 
@@ -103,20 +103,6 @@ namespace MediaBrowser.Controller.Channels
             return list;
             return list;
         }
         }
 
 
-        public ChannelItemLookupInfo GetLookupInfo()
-        {
-            var info = GetItemLookupInfo<ChannelItemLookupInfo>();
-
-            info.ContentType = ContentType;
-
-            if (ExtraType.HasValue)
-            {
-                info.ExtraType = ExtraType.Value;
-            }
-
-            return info;
-        }
-
         protected override string GetInternalMetadataPath(string basePath)
         protected override string GetInternalMetadataPath(string basePath)
         {
         {
             return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N"));
             return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N"));
@@ -132,7 +118,7 @@ namespace MediaBrowser.Controller.Channels
             return IsVisibleStandaloneInternal(user, false) && IsChannelVisible(this, user);
             return IsVisibleStandaloneInternal(user, false) && IsChannelVisible(this, user);
         }
         }
 
 
-        internal static bool IsChannelVisible(IChannelItem item, User user)
+        internal static bool IsChannelVisible(BaseItem item, User user)
         {
         {
             var channel = ChannelManager.GetChannel(item.ChannelId);
             var channel = ChannelManager.GetChannel(item.ChannelId);
 
 

+ 0 - 11
MediaBrowser.Controller/Channels/IChannelItem.cs

@@ -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; }
-    }
-}

+ 2 - 2
MediaBrowser.Controller/Channels/IChannelManager.cs

@@ -116,7 +116,7 @@ namespace MediaBrowser.Controller.Channels
         /// <param name="includeCachedVersions">if set to <c>true</c> [include cached versions].</param>
         /// <param name="includeCachedVersions">if set to <c>true</c> [include cached versions].</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task{IEnumerable{MediaSourceInfo}}.</returns>
         /// <returns>Task{IEnumerable{MediaSourceInfo}}.</returns>
-        Task<IEnumerable<MediaSourceInfo>> GetStaticMediaSources(IChannelMediaItem item, bool includeCachedVersions, CancellationToken cancellationToken);
+        Task<IEnumerable<MediaSourceInfo>> GetStaticMediaSources(BaseItem item, bool includeCachedVersions, CancellationToken cancellationToken);
 
 
         /// <summary>
         /// <summary>
         /// Gets the channel folder.
         /// Gets the channel folder.
@@ -141,6 +141,6 @@ namespace MediaBrowser.Controller.Channels
         /// <param name="progress">The progress.</param>
         /// <param name="progress">The progress.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task.</returns>
         /// <returns>Task.</returns>
-        Task DownloadChannelItem(IChannelMediaItem item, string destinationPath, IProgress<double> progress, CancellationToken cancellationToken);
+        Task DownloadChannelItem(BaseItem item, string destinationPath, IProgress<double> progress, CancellationToken cancellationToken);
     }
     }
 }
 }

+ 0 - 18
MediaBrowser.Controller/Channels/IChannelMediaItem.cs

@@ -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; }
-    }
-}

+ 35 - 1
MediaBrowser.Controller/Entities/Audio/Audio.cs

@@ -8,6 +8,8 @@ using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq;
 using System.Runtime.Serialization;
 using System.Runtime.Serialization;
+using System.Threading;
+using MediaBrowser.Controller.Channels;
 
 
 namespace MediaBrowser.Controller.Entities.Audio
 namespace MediaBrowser.Controller.Entities.Audio
 {
 {
@@ -24,6 +26,8 @@ namespace MediaBrowser.Controller.Entities.Audio
         IThemeMedia,
         IThemeMedia,
         IArchivable
         IArchivable
     {
     {
+        public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
+        
         public long? Size { get; set; }
         public long? Size { get; set; }
         public string Container { get; set; }
         public string Container { get; set; }
         public int? TotalBitrate { get; set; }
         public int? TotalBitrate { get; set; }
@@ -198,7 +202,11 @@ namespace MediaBrowser.Controller.Entities.Audio
 
 
         public override UnratedItem GetBlockUnratedType()
         public override UnratedItem GetBlockUnratedType()
         {
         {
-            return UnratedItem.Music;
+            if (SourceType == SourceType.Library)
+            {
+                return UnratedItem.Music;
+            }
+            return base.GetBlockUnratedType();
         }
         }
 
 
         public SongInfo GetLookupInfo()
         public SongInfo GetLookupInfo()
@@ -214,6 +222,32 @@ namespace MediaBrowser.Controller.Entities.Audio
 
 
         public virtual IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
         public virtual IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
         {
         {
+            if (SourceType == SourceType.Channel)
+            {
+                var sources = ChannelManager.GetStaticMediaSources(this, false, CancellationToken.None)
+                           .Result.ToList();
+
+                if (sources.Count > 0)
+                {
+                    return sources;
+                }
+
+                var list = new List<MediaSourceInfo>
+                {
+                    GetVersionInfo(this, enablePathSubstitution)
+                };
+
+                foreach (var mediaSource in list)
+                {
+                    if (string.IsNullOrWhiteSpace(mediaSource.Path))
+                    {
+                        mediaSource.Type = MediaSourceType.Placeholder;
+                    }
+                }
+
+                return list;
+            }
+
             var result = new List<MediaSourceInfo>
             var result = new List<MediaSourceInfo>
             {
             {
                 GetVersionInfo(this, enablePathSubstitution)
                 GetVersionInfo(this, enablePathSubstitution)

+ 12 - 0
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
+    {
+    }
+}

+ 45 - 0
MediaBrowser.Controller/Entities/BaseItem.cs

@@ -169,6 +169,9 @@ namespace MediaBrowser.Controller.Entities
         [IgnoreDataMember]
         [IgnoreDataMember]
         public bool IsOffline { get; set; }
         public bool IsOffline { get; set; }
 
 
+        [IgnoreDataMember]
+        public virtual SourceType SourceType { get; set; }
+
         /// <summary>
         /// <summary>
         /// Returns the folder containing the item.
         /// Returns the folder containing the item.
         /// If the item is a folder, it returns the folder itself
         /// If the item is a folder, it returns the folder itself
@@ -255,6 +258,11 @@ namespace MediaBrowser.Controller.Entities
         {
         {
             get
             get
             {
             {
+                if (SourceType == SourceType.Channel)
+                {
+                    return false;
+                }
+
                 var locationType = LocationType;
                 var locationType = LocationType;
 
 
                 return locationType != LocationType.Remote && locationType != LocationType.Virtual;
                 return locationType != LocationType.Remote && locationType != LocationType.Virtual;
@@ -301,6 +309,11 @@ namespace MediaBrowser.Controller.Entities
 
 
         public virtual bool CanDelete()
         public virtual bool CanDelete()
         {
         {
+            if (SourceType == SourceType.Channel)
+            {
+                return false;
+            }
+
             var locationType = LocationType;
             var locationType = LocationType;
             return locationType != LocationType.Remote &&
             return locationType != LocationType.Remote &&
                    locationType != LocationType.Virtual;
                    locationType != LocationType.Virtual;
@@ -460,6 +473,11 @@ namespace MediaBrowser.Controller.Entities
 
 
         protected virtual string GetInternalMetadataPath(string basePath)
         protected virtual string GetInternalMetadataPath(string basePath)
         {
         {
+            if (SourceType == SourceType.Channel)
+            {
+                return System.IO.Path.Combine(basePath, "channels", ChannelId, Id.ToString("N"));
+            }
+            
             var idString = Id.ToString("N");
             var idString = Id.ToString("N");
 
 
             basePath = System.IO.Path.Combine(basePath, "library");
             basePath = System.IO.Path.Combine(basePath, "library");
@@ -1032,6 +1050,13 @@ namespace MediaBrowser.Controller.Entities
 
 
         protected virtual string CreateUserDataKey()
         protected virtual string CreateUserDataKey()
         {
         {
+            if (SourceType == SourceType.Channel)
+            {
+                if (!string.IsNullOrWhiteSpace(ExternalId))
+                {
+                    return ExternalId;
+                }
+            }
             return Id.ToString();
             return Id.ToString();
         }
         }
 
 
@@ -1110,6 +1135,11 @@ namespace MediaBrowser.Controller.Entities
 
 
         public virtual bool IsSaveLocalMetadataEnabled()
         public virtual bool IsSaveLocalMetadataEnabled()
         {
         {
+            if (SourceType == SourceType.Channel)
+            {
+                return false;
+            }
+            
             return ConfigurationManager.Configuration.SaveLocalMeta;
             return ConfigurationManager.Configuration.SaveLocalMeta;
         }
         }
 
 
@@ -1225,6 +1255,11 @@ namespace MediaBrowser.Controller.Entities
 
 
         public virtual UnratedItem GetBlockUnratedType()
         public virtual UnratedItem GetBlockUnratedType()
         {
         {
+            if (SourceType == SourceType.Channel)
+            {
+                return UnratedItem.ChannelContent;
+            }
+
             return UnratedItem.Other;
             return UnratedItem.Other;
         }
         }
 
 
@@ -1268,6 +1303,11 @@ namespace MediaBrowser.Controller.Entities
 
 
         public virtual bool IsVisibleStandalone(User user)
         public virtual bool IsVisibleStandalone(User user)
         {
         {
+            if (SourceType == SourceType.Channel)
+            {
+                return IsVisibleStandaloneInternal(user, false) && Channel.IsChannelVisible(this, user);
+            }
+
             return IsVisibleStandaloneInternal(user, true);
             return IsVisibleStandaloneInternal(user, true);
         }
         }
 
 
@@ -1319,6 +1359,11 @@ namespace MediaBrowser.Controller.Entities
 
 
         public virtual string GetClientTypeName()
         public virtual string GetClientTypeName()
         {
         {
+            if (IsFolder && SourceType == SourceType.Channel)
+            {
+                return "ChannelFolderItem";
+            }
+
             return GetType().Name;
             return GetType().Name;
         }
         }
 
 

+ 30 - 2
MediaBrowser.Controller/Entities/Folder.cs

@@ -15,6 +15,7 @@ using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using CommonIO;
 using CommonIO;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.IO;
+using MediaBrowser.Model.Channels;
 
 
 namespace MediaBrowser.Controller.Entities
 namespace MediaBrowser.Controller.Entities
 {
 {
@@ -794,8 +795,35 @@ namespace MediaBrowser.Controller.Entities
             return item;
             return item;
         }
         }
 
 
-        public virtual Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
+        public virtual async Task<QueryResult<BaseItem>> GetItems(InternalItemsQuery query)
         {
         {
+            if (SourceType == SourceType.Channel)
+            {
+                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>
+                    {
+
+                    };
+                }
+            }
+            
             var user = query.User;
             var user = query.User;
 
 
             Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
             Func<BaseItem, bool> filter = i => UserViewBuilder.Filter(i, user, query, UserDataManager, LibraryManager);
@@ -817,7 +845,7 @@ namespace MediaBrowser.Controller.Entities
 
 
             var result = PostFilterAndSort(items, query);
             var result = PostFilterAndSort(items, query);
 
 
-            return Task.FromResult(result);
+            return result;
         }
         }
 
 
         protected QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, InternalItemsQuery query)
         protected QueryResult<BaseItem> PostFilterAndSort(IEnumerable<BaseItem> items, InternalItemsQuery query)

+ 8 - 0
MediaBrowser.Controller/Entities/InternalItemsQuery.cs

@@ -115,6 +115,10 @@ namespace MediaBrowser.Controller.Entities
 
 
         public LocationType[] ExcludeLocationTypes { get; set; }
         public LocationType[] ExcludeLocationTypes { get; set; }
         public string[] PresetViews { get; set; }
         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()
         public InternalItemsQuery()
         {
         {
@@ -141,6 +145,10 @@ namespace MediaBrowser.Controller.Entities
             ExcludeTags = new string[] { };
             ExcludeTags = new string[] { };
             ExcludeLocationTypes = new LocationType[] { };
             ExcludeLocationTypes = new LocationType[] { };
             PresetViews = new string[] { };
             PresetViews = new string[] { };
+            SourceTypes = new SourceType[] { };
+            ExcludeSourceTypes = new SourceType[] { };
+            TrailerTypes = new TrailerType[] { };
+            ExcludeTrailerTypes = new TrailerType[] { };
         }
         }
 
 
         public InternalItemsQuery(User user)
         public InternalItemsQuery(User user)

+ 10 - 0
MediaBrowser.Controller/Entities/SourceType.cs

@@ -0,0 +1,10 @@
+
+namespace MediaBrowser.Controller.Entities
+{
+    public enum SourceType
+    {
+        Library = 1,
+        Channel = 2,
+        LiveTV = 3
+    }
+}

+ 45 - 15
MediaBrowser.Controller/Entities/Trailer.cs

@@ -24,8 +24,11 @@ namespace MediaBrowser.Controller.Entities
             Taglines = new List<string>();
             Taglines = new List<string>();
             Keywords = new List<string>();
             Keywords = new List<string>();
             ProductionLocations = new List<string>();
             ProductionLocations = new List<string>();
+            TrailerTypes = new List<TrailerType>();
         }
         }
 
 
+        public List<TrailerType> TrailerTypes { get; set; }
+        
         public float? Metascore { get; set; }
         public float? Metascore { get; set; }
 
 
         public List<MediaUrl> RemoteTrailers { get; set; }
         public List<MediaUrl> RemoteTrailers { get; set; }
@@ -62,20 +65,6 @@ namespace MediaBrowser.Controller.Entities
         /// <value>The critic rating summary.</value>
         /// <value>The critic rating summary.</value>
         public string CriticRatingSummary { get; set; }
         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()
         protected override string CreateUserDataKey()
         {
         {
             var key = Movie.GetMovieUserDataKey(this);
             var key = Movie.GetMovieUserDataKey(this);
@@ -105,9 +94,50 @@ namespace MediaBrowser.Controller.Entities
         {
         {
             var info = GetItemLookupInfo<TrailerInfo>();
             var info = GetItemLookupInfo<TrailerInfo>();
 
 
-            info.IsLocalTrailer = IsLocalTrailer;
+            info.IsLocalTrailer = TrailerTypes.Contains(TrailerType.LocalTrailer);
+            
+            if (!IsInMixedFolder)
+            {
+                info.Name = System.IO.Path.GetFileName(ContainingFolderPath);
+            }
 
 
             return info;
             return info;
         }
         }
+
+        public override bool BeforeMetadataRefresh()
+        {
+            var hasChanges = base.BeforeMetadataRefresh();
+
+            if (!ProductionYear.HasValue)
+            {
+                var info = LibraryManager.ParseName(Name);
+
+                var yearInName = info.Year;
+
+                if (yearInName.HasValue)
+                {
+                    ProductionYear = yearInName;
+                    hasChanges = true;
+                }
+                else
+                {
+                    // Try to get the year from the folder name
+                    if (!IsInMixedFolder)
+                    {
+                        info = LibraryManager.ParseName(System.IO.Path.GetFileName(ContainingFolderPath));
+
+                        yearInName = info.Year;
+
+                        if (yearInName.HasValue)
+                        {
+                            ProductionYear = yearInName;
+                            hasChanges = true;
+                        }
+                    }
+                }
+            }
+
+            return hasChanges;
+        }
     }
     }
 }
 }

+ 60 - 0
MediaBrowser.Controller/Entities/Video.cs

@@ -6,13 +6,16 @@ using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.MediaInfo;
 using MediaBrowser.Model.MediaInfo;
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.Globalization;
 using System.IO;
 using System.IO;
 using System.Linq;
 using System.Linq;
+using System.Net.Mime;
 using System.Runtime.Serialization;
 using System.Runtime.Serialization;
 using System.Threading;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using CommonIO;
 using CommonIO;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.IO;
+using MediaBrowser.Controller.Channels;
 
 
 namespace MediaBrowser.Controller.Entities
 namespace MediaBrowser.Controller.Entities
 {
 {
@@ -33,6 +36,7 @@ namespace MediaBrowser.Controller.Entities
         public List<string> AdditionalParts { get; set; }
         public List<string> AdditionalParts { get; set; }
         public List<string> LocalAlternateVersions { get; set; }
         public List<string> LocalAlternateVersions { get; set; }
         public List<LinkedChild> LinkedAlternateVersions { get; set; }
         public List<LinkedChild> LinkedAlternateVersions { get; set; }
+        public List<ChannelMediaInfo> ChannelMediaSources { get; set; }
 
 
         [IgnoreDataMember]
         [IgnoreDataMember]
         public bool IsThemeMedia
         public bool IsThemeMedia
@@ -78,6 +82,23 @@ namespace MediaBrowser.Controller.Entities
                    locationType != LocationType.Virtual;
                    locationType != LocationType.Virtual;
         }
         }
 
 
+        [IgnoreDataMember]
+        public override LocationType LocationType
+        {
+            get
+            {
+                if (SourceType == SourceType.Channel)
+                {
+                    if (string.IsNullOrEmpty(Path))
+                    {
+                        return LocationType.Remote;
+                    }
+                }
+
+                return base.LocationType;
+            }
+        }
+
         [IgnoreDataMember]
         [IgnoreDataMember]
         public override bool SupportsAddingToPlaylist
         public override bool SupportsAddingToPlaylist
         {
         {
@@ -130,6 +151,29 @@ namespace MediaBrowser.Controller.Entities
             return LocalAlternateVersions.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
             return LocalAlternateVersions.Select(i => LibraryManager.GetNewItemId(i, typeof(Video)));
         }
         }
 
 
+        protected override string CreateUserDataKey()
+        {
+            if (ExtraType.HasValue)
+            {
+                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 base.CreateUserDataKey();
+        }
+
         /// <summary>
         /// <summary>
         /// Gets the linked children.
         /// Gets the linked children.
         /// </summary>
         /// </summary>
@@ -441,6 +485,22 @@ namespace MediaBrowser.Controller.Entities
 
 
         public virtual IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
         public virtual IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
         {
         {
+            if (SourceType == SourceType.Channel)
+            {
+                var sources = ChannelManager.GetStaticMediaSources(this, false, CancellationToken.None)
+                           .Result.ToList();
+
+                if (sources.Count > 0)
+                {
+                    return sources;
+                }
+
+                return new List<MediaSourceInfo>
+                {
+                    GetVersionInfo(enablePathSubstitution, this, MediaSourceType.Placeholder)
+                };
+            }
+
             var item = this;
             var item = this;
 
 
             var result = item.GetAlternateVersions()
             var result = item.GetAlternateVersions()

+ 7 - 0
MediaBrowser.Controller/LiveTv/LiveTvAudioRecording.cs

@@ -39,6 +39,13 @@ namespace MediaBrowser.Controller.LiveTv
         [IgnoreDataMember]
         [IgnoreDataMember]
         public bool IsPremiere { get; set; }
         public bool IsPremiere { get; set; }
 
 
+        [IgnoreDataMember]
+        public override SourceType SourceType
+        {
+            get { return SourceType.LiveTV; }
+            set { }
+        }
+
         /// <summary>
         /// <summary>
         /// Gets the user data key.
         /// Gets the user data key.
         /// </summary>
         /// </summary>

+ 7 - 0
MediaBrowser.Controller/LiveTv/LiveTvChannel.cs

@@ -40,6 +40,13 @@ namespace MediaBrowser.Controller.LiveTv
             }
             }
         }
         }
 
 
+        [IgnoreDataMember]
+        public override SourceType SourceType
+        {
+            get { return SourceType.LiveTV; }
+            set { }
+        }
+
         /// <summary>
         /// <summary>
         /// Gets or sets the number.
         /// Gets or sets the number.
         /// </summary>
         /// </summary>

+ 7 - 0
MediaBrowser.Controller/LiveTv/LiveTvProgram.cs

@@ -46,6 +46,13 @@ namespace MediaBrowser.Controller.LiveTv
         [IgnoreDataMember]
         [IgnoreDataMember]
         public string ServiceName { get; set; }
         public string ServiceName { get; set; }
 
 
+        [IgnoreDataMember]
+        public override SourceType SourceType
+        {
+            get { return SourceType.LiveTV; }
+            set { }
+        }
+
         /// <summary>
         /// <summary>
         /// The start date of the program, in UTC.
         /// The start date of the program, in UTC.
         /// </summary>
         /// </summary>

+ 7 - 0
MediaBrowser.Controller/LiveTv/LiveTvVideoRecording.cs

@@ -39,6 +39,13 @@ namespace MediaBrowser.Controller.LiveTv
         [IgnoreDataMember]
         [IgnoreDataMember]
         public bool IsPremiere { get; set; }
         public bool IsPremiere { get; set; }
 
 
+        [IgnoreDataMember]
+        public override SourceType SourceType
+        {
+            get { return SourceType.LiveTV; }
+            set { }
+        }
+
         /// <summary>
         /// <summary>
         /// Gets the user data key.
         /// Gets the user data key.
         /// </summary>
         /// </summary>

+ 9 - 1
MediaBrowser.Controller/LiveTv/RecordingGroup.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using System.Runtime.Serialization;
+using MediaBrowser.Controller.Entities;
 using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.Users;
 using MediaBrowser.Model.Users;
 
 
@@ -24,5 +25,12 @@ namespace MediaBrowser.Controller.LiveTv
                 return false;
                 return false;
             }
             }
         }
         }
+
+        [IgnoreDataMember]
+        public override SourceType SourceType
+        {
+            get { return SourceType.LiveTV; }
+            set { }
+        }
     }
     }
 }
 }

+ 4 - 5
MediaBrowser.Controller/MediaBrowser.Controller.csproj

@@ -75,6 +75,7 @@
     </Compile>
     </Compile>
     <Compile Include="Activity\IActivityManager.cs" />
     <Compile Include="Activity\IActivityManager.cs" />
     <Compile Include="Activity\IActivityRepository.cs" />
     <Compile Include="Activity\IActivityRepository.cs" />
+    <Compile Include="Channels\ChannelAudioItem.cs" />
     <Compile Include="Channels\ChannelFolderItem.cs" />
     <Compile Include="Channels\ChannelFolderItem.cs" />
     <Compile Include="Channels\ChannelItemInfo.cs" />
     <Compile Include="Channels\ChannelItemInfo.cs" />
     <Compile Include="Channels\ChannelItemResult.cs" />
     <Compile Include="Channels\ChannelItemResult.cs" />
@@ -82,13 +83,10 @@
     <Compile Include="Channels\ChannelMediaInfo.cs" />
     <Compile Include="Channels\ChannelMediaInfo.cs" />
     <Compile Include="Channels\ChannelParentalRating.cs" />
     <Compile Include="Channels\ChannelParentalRating.cs" />
     <Compile Include="Channels\ChannelSearchInfo.cs" />
     <Compile Include="Channels\ChannelSearchInfo.cs" />
+    <Compile Include="Channels\ChannelVideoItem.cs" />
     <Compile Include="Channels\IChannel.cs" />
     <Compile Include="Channels\IChannel.cs" />
     <Compile Include="Channels\IChannelManager.cs" />
     <Compile Include="Channels\IChannelManager.cs" />
-    <Compile Include="Channels\IChannelItem.cs" />
-    <Compile Include="Channels\ChannelAudioItem.cs" />
-    <Compile Include="Channels\ChannelVideoItem.cs" />
     <Compile Include="Channels\Channel.cs" />
     <Compile Include="Channels\Channel.cs" />
-    <Compile Include="Channels\IChannelMediaItem.cs" />
     <Compile Include="Channels\IHasCacheKey.cs" />
     <Compile Include="Channels\IHasCacheKey.cs" />
     <Compile Include="Channels\IIndexableChannel.cs" />
     <Compile Include="Channels\IIndexableChannel.cs" />
     <Compile Include="Channels\InternalAllChannelMediaQuery.cs" />
     <Compile Include="Channels\InternalAllChannelMediaQuery.cs" />
@@ -128,6 +126,7 @@
     <Compile Include="Drawing\ImageStream.cs" />
     <Compile Include="Drawing\ImageStream.cs" />
     <Compile Include="Dto\DtoOptions.cs" />
     <Compile Include="Dto\DtoOptions.cs" />
     <Compile Include="Dto\IDtoService.cs" />
     <Compile Include="Dto\IDtoService.cs" />
+    <Compile Include="Entities\Audio\AudioPodcast.cs" />
     <Compile Include="Entities\Audio\IHasAlbumArtist.cs" />
     <Compile Include="Entities\Audio\IHasAlbumArtist.cs" />
     <Compile Include="Entities\Audio\IHasMusicGenres.cs" />
     <Compile Include="Entities\Audio\IHasMusicGenres.cs" />
     <Compile Include="Entities\Book.cs" />
     <Compile Include="Entities\Book.cs" />
@@ -180,6 +179,7 @@
     <Compile Include="Entities\Photo.cs" />
     <Compile Include="Entities\Photo.cs" />
     <Compile Include="Entities\PhotoAlbum.cs" />
     <Compile Include="Entities\PhotoAlbum.cs" />
     <Compile Include="Entities\Share.cs" />
     <Compile Include="Entities\Share.cs" />
+    <Compile Include="Entities\SourceType.cs" />
     <Compile Include="Entities\UserView.cs" />
     <Compile Include="Entities\UserView.cs" />
     <Compile Include="Entities\UserViewBuilder.cs" />
     <Compile Include="Entities\UserViewBuilder.cs" />
     <Compile Include="FileOrganization\IFileOrganizationService.cs" />
     <Compile Include="FileOrganization\IFileOrganizationService.cs" />
@@ -271,7 +271,6 @@
     <Compile Include="Providers\ArtistInfo.cs" />
     <Compile Include="Providers\ArtistInfo.cs" />
     <Compile Include="Providers\BookInfo.cs" />
     <Compile Include="Providers\BookInfo.cs" />
     <Compile Include="Providers\BoxSetInfo.cs" />
     <Compile Include="Providers\BoxSetInfo.cs" />
-    <Compile Include="Providers\ChannelItemLookupInfo.cs" />
     <Compile Include="Providers\DirectoryService.cs" />
     <Compile Include="Providers\DirectoryService.cs" />
     <Compile Include="Providers\DynamicImageInfo.cs" />
     <Compile Include="Providers\DynamicImageInfo.cs" />
     <Compile Include="Providers\DynamicImageResponse.cs" />
     <Compile Include="Providers\DynamicImageResponse.cs" />

+ 0 - 11
MediaBrowser.Controller/Providers/ChannelItemLookupInfo.cs

@@ -1,11 +0,0 @@
-using MediaBrowser.Model.Channels;
-using MediaBrowser.Model.Entities;
-
-namespace MediaBrowser.Controller.Providers
-{
-    public class ChannelItemLookupInfo : ItemLookupInfo
-    {
-        public ChannelMediaContentType ContentType { get; set; }
-        public ExtraType ExtraType { get; set; }
-    }
-}

+ 2 - 0
MediaBrowser.Controller/Providers/TrailerInfo.cs

@@ -1,3 +1,5 @@
+using MediaBrowser.Model.Entities;
+
 namespace MediaBrowser.Controller.Providers
 namespace MediaBrowser.Controller.Providers
 {
 {
     public class TrailerInfo : ItemLookupInfo
     public class TrailerInfo : ItemLookupInfo

+ 1 - 1
MediaBrowser.Dlna/ContentDirectory/ControlHandler.cs

@@ -488,7 +488,7 @@ namespace MediaBrowser.Dlna.ContentDirectory
             var itemsResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
             var itemsResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
             {
             {
                 Person = person.Name,
                 Person = person.Name,
-                IncludeItemTypes = new[] { typeof(Movie).Name, typeof(Series).Name, typeof(Trailer).Name, typeof(ChannelVideoItem).Name },
+                IncludeItemTypes = new[] { typeof(Movie).Name, typeof(Series).Name, typeof(Trailer).Name },
                 SortBy = new[] { ItemSortBy.SortName },
                 SortBy = new[] { ItemSortBy.SortName },
                 Limit = limit,
                 Limit = limit,
                 StartIndex = startIndex
                 StartIndex = startIndex

+ 4 - 4
MediaBrowser.Dlna/Profiles/DefaultProfile.cs

@@ -31,10 +31,10 @@ namespace MediaBrowser.Dlna.Profiles
             MaxIconWidth = 48;
             MaxIconWidth = 48;
             MaxIconHeight = 48;
             MaxIconHeight = 48;
 
 
-            MaxStreamingBitrate = 12000000;
-            MaxStaticBitrate = 12000000;
-            MusicStreamingTranscodingBitrate = 128000;
-            MusicSyncBitrate = 128000;
+            MaxStreamingBitrate = 15000000;
+            MaxStaticBitrate = 15000000;
+            MusicStreamingTranscodingBitrate = 192000;
+            MusicSyncBitrate = 192000;
 
 
             EnableAlbumArtInDidl = false;
             EnableAlbumArtInDidl = false;
 
 

+ 42 - 0
MediaBrowser.Dlna/Profiles/KodiProfile.cs

@@ -99,6 +99,48 @@ namespace MediaBrowser.Dlna.Profiles
                     DidlMode = "",
                     DidlMode = "",
                 },
                 },
 
 
+                new SubtitleProfile
+                {
+                    Format = "ass",
+                    Method = SubtitleDeliveryMethod.Embed,
+                    DidlMode = "",
+                },
+
+                new SubtitleProfile
+                {
+                    Format = "ssa",
+                    Method = SubtitleDeliveryMethod.Embed,
+                    DidlMode = "",
+                },
+
+                new SubtitleProfile
+                {
+                    Format = "smi",
+                    Method = SubtitleDeliveryMethod.Embed,
+                    DidlMode = "",
+                },
+
+                new SubtitleProfile
+                {
+                    Format = "dvdsub",
+                    Method = SubtitleDeliveryMethod.Embed,
+                    DidlMode = "",
+                },
+
+                new SubtitleProfile
+                {
+                    Format = "pgs",
+                    Method = SubtitleDeliveryMethod.Embed,
+                    DidlMode = "",
+                },
+
+                new SubtitleProfile
+                {
+                    Format = "pgssub",
+                    Method = SubtitleDeliveryMethod.Embed,
+                    DidlMode = "",
+                },
+
                 new SubtitleProfile
                 new SubtitleProfile
                 {
                 {
                     Format = "sub",
                     Format = "sub",

File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/BubbleUPnp.xml


File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/Default.xml


File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/Denon AVR.xml


File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/DirecTV HD-DVR.xml


+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/Dish Hopper-Joey.xml

@@ -24,10 +24,10 @@
   <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
   <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
   <MaxIconWidth>48</MaxIconWidth>
   <MaxIconWidth>48</MaxIconWidth>
   <MaxIconHeight>48</MaxIconHeight>
   <MaxIconHeight>48</MaxIconHeight>
-  <MaxStreamingBitrate>12000000</MaxStreamingBitrate>
-  <MaxStaticBitrate>12000000</MaxStaticBitrate>
-  <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
-  <MusicSyncBitrate>128000</MusicSyncBitrate>
+  <MaxStreamingBitrate>15000000</MaxStreamingBitrate>
+  <MaxStaticBitrate>15000000</MaxStaticBitrate>
+  <MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
+  <MusicSyncBitrate>192000</MusicSyncBitrate>
   <XDlnaDoc>DMS-1.50</XDlnaDoc>
   <XDlnaDoc>DMS-1.50</XDlnaDoc>
   <ProtocolInfo>http-get:*:video/mp2t:*,http-get:*:video/MP1S:*,http-get:*:video/mpeg2:*,http-get:*:video/mp4:*,http-get:*:video/x-matroska:*,http-get:*:audio/mpeg:*,http-get:*:audio/mpeg3:*,http-get:*:audio/mp3:*,http-get:*:audio/mp4:*,http-get:*:audio/mp4a-latm:*,http-get:*:image/jpeg:*</ProtocolInfo>
   <ProtocolInfo>http-get:*:video/mp2t:*,http-get:*:video/MP1S:*,http-get:*:video/mpeg2:*,http-get:*:video/mp4:*,http-get:*:video/x-matroska:*,http-get:*:audio/mpeg:*,http-get:*:audio/mpeg3:*,http-get:*:audio/mp3:*,http-get:*:audio/mp4:*,http-get:*:audio/mp4a-latm:*,http-get:*:image/jpeg:*</ProtocolInfo>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>
   <TimelineOffsetSeconds>0</TimelineOffsetSeconds>

+ 6 - 0
MediaBrowser.Dlna/Profiles/Xml/Kodi.xml

@@ -52,6 +52,12 @@
     <SubtitleProfile format="srt" method="External" />
     <SubtitleProfile format="srt" method="External" />
     <SubtitleProfile format="sub" method="External" />
     <SubtitleProfile format="sub" method="External" />
     <SubtitleProfile format="srt" method="Embed" didlMode="" />
     <SubtitleProfile format="srt" method="Embed" didlMode="" />
+    <SubtitleProfile format="ass" method="Embed" didlMode="" />
+    <SubtitleProfile format="ssa" method="Embed" didlMode="" />
+    <SubtitleProfile format="smi" method="Embed" didlMode="" />
+    <SubtitleProfile format="dvdsub" method="Embed" didlMode="" />
+    <SubtitleProfile format="pgs" method="Embed" didlMode="" />
+    <SubtitleProfile format="pgssub" method="Embed" didlMode="" />
     <SubtitleProfile format="sub" method="Embed" didlMode="" />
     <SubtitleProfile format="sub" method="Embed" didlMode="" />
   </SubtitleProfiles>
   </SubtitleProfiles>
 </Profile>
 </Profile>

File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/LG Smart TV.xml


File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/Linksys DMA2100.xml


File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/MediaMonkey.xml


File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/Panasonic Viera.xml


File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/Popcorn Hour.xml


File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/Samsung Smart TV.xml


File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player 2013.xml


File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/Sony Blu-ray Player.xml


+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2010).xml

@@ -24,10 +24,10 @@
   <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
   <MaxAlbumArtHeight>480</MaxAlbumArtHeight>
   <MaxIconWidth>48</MaxIconWidth>
   <MaxIconWidth>48</MaxIconWidth>
   <MaxIconHeight>48</MaxIconHeight>
   <MaxIconHeight>48</MaxIconHeight>
-  <MaxStreamingBitrate>12000000</MaxStreamingBitrate>
-  <MaxStaticBitrate>12000000</MaxStaticBitrate>
-  <MusicStreamingTranscodingBitrate>128000</MusicStreamingTranscodingBitrate>
-  <MusicSyncBitrate>128000</MusicSyncBitrate>
+  <MaxStreamingBitrate>15000000</MaxStreamingBitrate>
+  <MaxStaticBitrate>15000000</MaxStaticBitrate>
+  <MusicStreamingTranscodingBitrate>192000</MusicStreamingTranscodingBitrate>
+  <MusicSyncBitrate>192000</MusicSyncBitrate>
   <XDlnaDoc>DMS-1.50</XDlnaDoc>
   <XDlnaDoc>DMS-1.50</XDlnaDoc>
   <SonyAggregationFlags>10</SonyAggregationFlags>
   <SonyAggregationFlags>10</SonyAggregationFlags>
   <ProtocolInfo>http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000</ProtocolInfo>
   <ProtocolInfo>http-get:*:audio/mpeg:DLNA.ORG_PN=MP3;DLNA.ORG_OP=01;DLNA.ORG_FLAGS=81500000000000000000000000000000,http-get:*:image/jpeg:DLNA.ORG_PN=JPEG_SM;DLNA.ORG_OP=00;DLNA.ORG_FLAGS=00D00000000000000000000000000000,http-get:*:video/mpeg:DLNA.ORG_PN=MPEG_PS_PAL;DLNA.ORG_OP=11;DLNA.ORG_FLAGS=81500000000000000000000000000000</ProtocolInfo>

File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2011).xml


File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2012).xml


File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2013).xml


File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/Sony Bravia (2014).xml


File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 3.xml


File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/Sony PlayStation 4.xml


File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/Vlc.xml


File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/WDTV Live.xml


File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/Xbox 360.xml


File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/Xbox One.xml


File diff suppressed because it is too large
+ 4 - 4
MediaBrowser.Dlna/Profiles/Xml/foobar2000.xml


+ 4 - 4
MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs

@@ -293,10 +293,10 @@ namespace MediaBrowser.MediaEncoding.Encoder
             }
             }
 
 
             var formats = (video.Container ?? string.Empty).Split(',').ToList();
             var formats = (video.Container ?? string.Empty).Split(',').ToList();
-            var enableInterlacedDection = formats.Contains("vob", StringComparer.OrdinalIgnoreCase) &&
-                                          formats.Contains("m2ts", StringComparer.OrdinalIgnoreCase) &&
-                                          formats.Contains("ts", StringComparer.OrdinalIgnoreCase) &&
-                                          formats.Contains("mpegts", StringComparer.OrdinalIgnoreCase) &&
+            var enableInterlacedDection = formats.Contains("vob", StringComparer.OrdinalIgnoreCase) ||
+                                          formats.Contains("m2ts", StringComparer.OrdinalIgnoreCase) ||
+                                          formats.Contains("ts", StringComparer.OrdinalIgnoreCase) ||
+                                          formats.Contains("mpegts", StringComparer.OrdinalIgnoreCase) ||
                                           formats.Contains("wtv", StringComparer.OrdinalIgnoreCase);
                                           formats.Contains("wtv", StringComparer.OrdinalIgnoreCase);
             
             
             // If it's mpeg based, assume true
             // If it's mpeg based, assume true

+ 6 - 0
MediaBrowser.Model/Dto/BaseItemDto.cs

@@ -43,6 +43,12 @@ namespace MediaBrowser.Model.Dto
         /// </summary>
         /// </summary>
         /// <value>The etag.</value>
         /// <value>The etag.</value>
         public string Etag { get; set; }
         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>
         /// <summary>
         /// Gets or sets the playlist item identifier.
         /// Gets or sets the playlist item identifier.

+ 2 - 1
MediaBrowser.Model/Entities/TrailerType.cs

@@ -5,6 +5,7 @@ namespace MediaBrowser.Model.Entities
         ComingSoonToTheaters = 1,
         ComingSoonToTheaters = 1,
         ComingSoonToDvd = 2,
         ComingSoonToDvd = 2,
         ComingSoonToStreaming = 3,
         ComingSoonToStreaming = 3,
-        Archive = 4
+        Archive = 4,
+        LocalTrailer = 5
     }
     }
 }
 }

+ 0 - 25
MediaBrowser.Providers/Channels/AudioChannelItemMetadataService.cs

@@ -1,25 +0,0 @@
-using System.Collections.Generic;
-using CommonIO;
-using MediaBrowser.Common.IO;
-using MediaBrowser.Controller.Channels;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Providers.Manager;
-
-namespace MediaBrowser.Providers.Channels
-{
-    public class AudioChannelItemMetadataService : MetadataService<ChannelAudioItem, ItemLookupInfo>
-    {
-        public AudioChannelItemMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager, libraryManager)
-        {
-        }
-
-        protected override void MergeData(MetadataResult<ChannelAudioItem> source, MetadataResult<ChannelAudioItem> target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings)
-        {
-            ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
-        }
-    }
-}

+ 0 - 25
MediaBrowser.Providers/Channels/VideoChannelItemMetadataService.cs

@@ -1,25 +0,0 @@
-using MediaBrowser.Common.IO;
-using MediaBrowser.Controller.Channels;
-using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Providers.Manager;
-using System.Collections.Generic;
-using CommonIO;
-
-namespace MediaBrowser.Providers.Channels
-{
-    public class VideoChannelItemMetadataService : MetadataService<ChannelVideoItem, ChannelItemLookupInfo>
-    {
-        public VideoChannelItemMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager) : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager, libraryManager)
-        {
-        }
-
-        protected override void MergeData(MetadataResult<ChannelVideoItem> source, MetadataResult<ChannelVideoItem> target, List<MetadataFields> lockedFields, bool replaceData, bool mergeMetadataSettings)
-        {
-            ProviderUtils.MergeBaseItemData(source, target, lockedFields, replaceData, mergeMetadataSettings);
-        }
-    }
-}

+ 0 - 2
MediaBrowser.Providers/MediaBrowser.Providers.csproj

@@ -90,10 +90,8 @@
     <Compile Include="Chapters\ChapterManager.cs" />
     <Compile Include="Chapters\ChapterManager.cs" />
     <Compile Include="Folders\DefaultImageProvider.cs" />
     <Compile Include="Folders\DefaultImageProvider.cs" />
     <Compile Include="Folders\FolderMetadataService.cs" />
     <Compile Include="Folders\FolderMetadataService.cs" />
-    <Compile Include="Channels\AudioChannelItemMetadataService.cs" />
     <Compile Include="Folders\UserViewMetadataService.cs" />
     <Compile Include="Folders\UserViewMetadataService.cs" />
     <Compile Include="GameGenres\GameGenreMetadataService.cs" />
     <Compile Include="GameGenres\GameGenreMetadataService.cs" />
-    <Compile Include="Channels\VideoChannelItemMetadataService.cs" />
     <Compile Include="Games\GameMetadataService.cs" />
     <Compile Include="Games\GameMetadataService.cs" />
     <Compile Include="Games\GameSystemMetadataService.cs" />
     <Compile Include="Games\GameSystemMetadataService.cs" />
     <Compile Include="Genres\GenreMetadataService.cs" />
     <Compile Include="Genres\GenreMetadataService.cs" />

+ 1 - 18
MediaBrowser.Providers/Movies/MovieDbImageProvider.cs

@@ -42,23 +42,6 @@ namespace MediaBrowser.Providers.Movies
 
 
         public bool Supports(IHasImages item)
         public bool Supports(IHasImages item)
         {
         {
-            var channelItem = item as IChannelMediaItem;
-
-            if (channelItem != null)
-            {
-                if (channelItem.ContentType == ChannelMediaContentType.Movie)
-                {
-                    return true;
-                }
-                if (channelItem.ContentType == ChannelMediaContentType.MovieExtra)
-                {
-                    if (channelItem.ExtraType == ExtraType.Trailer)
-                    {
-                        return true;
-                    }
-                }
-            }
-
             // Supports images for tv movies
             // Supports images for tv movies
             var tvProgram = item as LiveTvProgram;
             var tvProgram = item as LiveTvProgram;
             if (tvProgram != null && tvProgram.IsMovie)
             if (tvProgram != null && tvProgram.IsMovie)
@@ -66,7 +49,7 @@ namespace MediaBrowser.Providers.Movies
                 return true;
                 return true;
             }
             }
 
 
-            return item is Movie || item is MusicVideo;
+            return item is Movie || item is MusicVideo || item is Trailer;
         }
         }
 
 
         public IEnumerable<ImageType> GetSupportedImages(IHasImages item)
         public IEnumerable<ImageType> GetSupportedImages(IHasImages item)

+ 3 - 18
MediaBrowser.Providers/Movies/MovieDbTrailerProvider.cs

@@ -12,7 +12,7 @@ using System.Threading.Tasks;
 
 
 namespace MediaBrowser.Providers.Movies
 namespace MediaBrowser.Providers.Movies
 {
 {
-    public class MovieDbTrailerProvider : IHasOrder, IRemoteMetadataProvider<ChannelVideoItem, ChannelItemLookupInfo>
+    public class MovieDbTrailerProvider : IHasOrder, IRemoteMetadataProvider<Trailer, TrailerInfo>
     {
     {
         private readonly IHttpClient _httpClient;
         private readonly IHttpClient _httpClient;
 
 
@@ -26,24 +26,9 @@ namespace MediaBrowser.Providers.Movies
             return MovieDbProvider.Current.GetMovieSearchResults(searchInfo, cancellationToken);
             return MovieDbProvider.Current.GetMovieSearchResults(searchInfo, cancellationToken);
         }
         }
 
 
-        public Task<MetadataResult<ChannelVideoItem>> GetMetadata(ChannelItemLookupInfo info, CancellationToken cancellationToken)
+        public Task<MetadataResult<Trailer>> GetMetadata(TrailerInfo info, CancellationToken cancellationToken)
         {
         {
-            if (info.ContentType != ChannelMediaContentType.MovieExtra || info.ExtraType != ExtraType.Trailer)
-            {
-                return Task.FromResult(new MetadataResult<ChannelVideoItem>());
-            }
-
-            return MovieDbProvider.Current.GetItemMetadata<ChannelVideoItem>(info, cancellationToken);
-        }
-
-        public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ChannelItemLookupInfo info, CancellationToken cancellationToken)
-        {
-            if (info.ContentType != ChannelMediaContentType.MovieExtra || info.ExtraType != ExtraType.Trailer)
-            {
-                return Task.FromResult<IEnumerable<RemoteSearchResult>>(new List<RemoteSearchResult>());
-            }
-
-            return MovieDbProvider.Current.GetMovieSearchResults(info, cancellationToken);
+            return MovieDbProvider.Current.GetItemMetadata<Trailer>(info, cancellationToken);
         }
         }
 
 
         public string Name
         public string Name

+ 3 - 17
MediaBrowser.Providers/Movies/MovieExternalIds.cs

@@ -28,13 +28,6 @@ namespace MediaBrowser.Providers.Movies
 
 
         public bool Supports(IHasProviderIds item)
         public bool Supports(IHasProviderIds item)
         {
         {
-            var channelItem = item as ChannelVideoItem;
-
-            if (channelItem != null && channelItem.ContentType == ChannelMediaContentType.MovieExtra && channelItem.ExtraType == ExtraType.Trailer)
-            {
-                return true;
-            }
-
             // Supports images for tv movies
             // Supports images for tv movies
             var tvProgram = item as LiveTvProgram;
             var tvProgram = item as LiveTvProgram;
             if (tvProgram != null && tvProgram.IsMovie)
             if (tvProgram != null && tvProgram.IsMovie)
@@ -42,7 +35,7 @@ namespace MediaBrowser.Providers.Movies
                 return true;
                 return true;
             }
             }
 
 
-            return item is Movie || item is MusicVideo;
+            return item is Movie || item is MusicVideo || item is Trailer;
         }
         }
     }
     }
 
 
@@ -88,7 +81,7 @@ namespace MediaBrowser.Providers.Movies
 
 
         public bool Supports(IHasProviderIds item)
         public bool Supports(IHasProviderIds item)
         {
         {
-            return item is Movie || item is MusicVideo;
+            return item is Movie || item is MusicVideo || item is Trailer;
         }
         }
     }
     }
 
 
@@ -157,14 +150,7 @@ namespace MediaBrowser.Providers.Movies
 
 
         public bool Supports(IHasProviderIds item)
         public bool Supports(IHasProviderIds item)
         {
         {
-            var channelItem = item as ChannelVideoItem;
-
-            if (channelItem != null && channelItem.ContentType == ChannelMediaContentType.MovieExtra && channelItem.ExtraType == ExtraType.Trailer)
-            {
-                return true;
-            }
-
-            return item is Movie || item is MusicVideo || item is Series || item is Episode;
+            return item is Movie || item is MusicVideo || item is Series || item is Episode || item is Trailer;
         }
         }
     }
     }
 
 

+ 34 - 2
MediaBrowser.Providers/Movies/MovieMetadataService.cs

@@ -1,5 +1,4 @@
-using MediaBrowser.Common.IO;
-using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities.Movies;
 using MediaBrowser.Controller.Entities.Movies;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Controller.Providers;
@@ -8,6 +7,7 @@ using MediaBrowser.Model.Logging;
 using MediaBrowser.Providers.Manager;
 using MediaBrowser.Providers.Manager;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using CommonIO;
 using CommonIO;
+using MediaBrowser.Controller.Entities;
 
 
 namespace MediaBrowser.Providers.Movies
 namespace MediaBrowser.Providers.Movies
 {
 {
@@ -43,4 +43,36 @@ namespace MediaBrowser.Providers.Movies
             }
             }
         }
         }
     }
     }
+
+    public class TrailerMetadataService : MetadataService<Trailer, TrailerInfo>
+    {
+        public TrailerMetadataService(IServerConfigurationManager serverConfigurationManager, ILogger logger, IProviderManager providerManager, IProviderRepository providerRepo, IFileSystem fileSystem, IUserDataManager userDataManager, ILibraryManager libraryManager)
+            : base(serverConfigurationManager, logger, providerManager, providerRepo, fileSystem, userDataManager, libraryManager)
+        {
+        }
+
+        protected override bool IsFullLocalMetadata(Trailer item)
+        {
+            if (string.IsNullOrWhiteSpace(item.Overview))
+            {
+                return false;
+            }
+            if (!item.ProductionYear.HasValue)
+            {
+                return false;
+            }
+            return base.IsFullLocalMetadata(item);
+        }
+
+        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;
+            }
+        }
+    }
+
 }
 }

+ 1 - 18
MediaBrowser.Providers/Omdb/OmdbImageProvider.cs

@@ -81,23 +81,6 @@ namespace MediaBrowser.Providers.Omdb
                 return false;
                 return false;
             }
             }
 
 
-            var channelItem = item as IChannelMediaItem;
-
-            if (channelItem != null)
-            {
-                if (channelItem.ContentType == ChannelMediaContentType.Movie)
-                {
-                    return true;
-                }
-                if (channelItem.ContentType == ChannelMediaContentType.MovieExtra)
-                {
-                    if (channelItem.ExtraType == ExtraType.Trailer)
-                    {
-                        return true;
-                    }
-                }
-            }
-
             // Supports images for tv movies
             // Supports images for tv movies
             var tvProgram = item as LiveTvProgram;
             var tvProgram = item as LiveTvProgram;
             if (tvProgram != null && tvProgram.IsMovie)
             if (tvProgram != null && tvProgram.IsMovie)
@@ -105,7 +88,7 @@ namespace MediaBrowser.Providers.Omdb
                 return true;
                 return true;
             }
             }
 
 
-            return item is Movie;
+            return item is Movie || item is Trailer;
         }
         }
 
 
         public int Order
         public int Order

+ 4 - 14
MediaBrowser.Providers/Omdb/OmdbItemProvider.cs

@@ -22,7 +22,7 @@ using System.Threading.Tasks;
 namespace MediaBrowser.Providers.Omdb
 namespace MediaBrowser.Providers.Omdb
 {
 {
     public class OmdbItemProvider : IRemoteMetadataProvider<Series, SeriesInfo>,
     public class OmdbItemProvider : IRemoteMetadataProvider<Series, SeriesInfo>,
-        IRemoteMetadataProvider<Movie, MovieInfo>, IRemoteMetadataProvider<ChannelVideoItem, ChannelItemLookupInfo>, IRemoteMetadataProvider<LiveTvProgram, LiveTvProgramLookupInfo>
+        IRemoteMetadataProvider<Movie, MovieInfo>, IRemoteMetadataProvider<Trailer, TrailerInfo>, IRemoteMetadataProvider<LiveTvProgram, LiveTvProgramLookupInfo>
     {
     {
         private readonly IJsonSerializer _jsonSerializer;
         private readonly IJsonSerializer _jsonSerializer;
         private readonly IHttpClient _httpClient;
         private readonly IHttpClient _httpClient;
@@ -196,23 +196,13 @@ namespace MediaBrowser.Providers.Omdb
             return list;
             return list;
         }
         }
 
 
-        public Task<MetadataResult<ChannelVideoItem>> GetMetadata(ChannelItemLookupInfo info, CancellationToken cancellationToken)
+        public Task<MetadataResult<Trailer>> GetMetadata(TrailerInfo info, CancellationToken cancellationToken)
         {
         {
-            if (info.ContentType != ChannelMediaContentType.MovieExtra || info.ExtraType != ExtraType.Trailer)
-            {
-                return Task.FromResult(new MetadataResult<ChannelVideoItem>());
-            }
-
-            return GetMovieResult<ChannelVideoItem>(info, cancellationToken);
+            return GetMovieResult<Trailer>(info, cancellationToken);
         }
         }
 
 
-        public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ChannelItemLookupInfo searchInfo, CancellationToken cancellationToken)
+        public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(TrailerInfo searchInfo, CancellationToken cancellationToken)
         {
         {
-            if (searchInfo.ContentType != ChannelMediaContentType.MovieExtra || searchInfo.ExtraType != ExtraType.Trailer)
-            {
-                return Task.FromResult<IEnumerable<RemoteSearchResult>>(new List<RemoteSearchResult>());
-            }
-
             return GetSearchResults(searchInfo, "movie", cancellationToken);
             return GetSearchResults(searchInfo, "movie", cancellationToken);
         }
         }
 
 

+ 3 - 3
MediaBrowser.Server.Implementations/Channels/ChannelDynamicMediaSourceProvider.cs

@@ -20,11 +20,11 @@ namespace MediaBrowser.Server.Implementations.Channels
 
 
         public Task<IEnumerable<MediaSourceInfo>> GetMediaSources(IHasMediaSources item, CancellationToken cancellationToken)
         public Task<IEnumerable<MediaSourceInfo>> GetMediaSources(IHasMediaSources item, CancellationToken cancellationToken)
         {
         {
-            var channelItem = item as IChannelMediaItem;
+            var baseItem = (BaseItem) item;
 
 
-            if (channelItem != null)
+            if (baseItem.SourceType == SourceType.Channel)
             {
             {
-                return _channelManager.GetDynamicMediaSources(channelItem, cancellationToken);
+                return _channelManager.GetDynamicMediaSources(baseItem, cancellationToken);
             }
             }
 
 
             return Task.FromResult<IEnumerable<MediaSourceInfo>>(new List<MediaSourceInfo>());
             return Task.FromResult<IEnumerable<MediaSourceInfo>>(new List<MediaSourceInfo>());

+ 104 - 28
MediaBrowser.Server.Implementations/Channels/ChannelManager.cs

@@ -26,6 +26,9 @@ using System.Net;
 using System.Threading;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using CommonIO;
 using CommonIO;
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Entities.Movies;
+using MediaBrowser.Controller.Entities.TV;
 
 
 namespace MediaBrowser.Server.Implementations.Channels
 namespace MediaBrowser.Server.Implementations.Channels
 {
 {
@@ -248,9 +251,19 @@ namespace MediaBrowser.Server.Implementations.Channels
             return item;
             return item;
         }
         }
 
 
-        public async Task<IEnumerable<MediaSourceInfo>> GetStaticMediaSources(IChannelMediaItem item, bool includeCachedVersions, CancellationToken cancellationToken)
+        public async Task<IEnumerable<MediaSourceInfo>> GetStaticMediaSources(BaseItem item, bool includeCachedVersions, CancellationToken cancellationToken)
         {
         {
-            IEnumerable<ChannelMediaInfo> results = item.ChannelMediaSources;
+            IEnumerable<ChannelMediaInfo> results = new List<ChannelMediaInfo>();
+            var video = item as Video;
+            if (video != null)
+            {
+                results = video.ChannelMediaSources;
+            }
+            var audio = item as Audio;
+            if (audio != null)
+            {
+                results = audio.ChannelMediaSources ?? new List<ChannelMediaInfo>();
+            }
 
 
             var sources = SortMediaInfoResults(results)
             var sources = SortMediaInfoResults(results)
                 .Select(i => GetMediaSource(item, i))
                 .Select(i => GetMediaSource(item, i))
@@ -265,7 +278,7 @@ namespace MediaBrowser.Server.Implementations.Channels
             return sources;
             return sources;
         }
         }
 
 
-        public async Task<IEnumerable<MediaSourceInfo>> GetDynamicMediaSources(IChannelMediaItem item, CancellationToken cancellationToken)
+        public async Task<IEnumerable<MediaSourceInfo>> GetDynamicMediaSources(BaseItem item, CancellationToken cancellationToken)
         {
         {
             var channel = GetChannel(item.ChannelId);
             var channel = GetChannel(item.ChannelId);
             var channelPlugin = GetChannelProvider(channel);
             var channelPlugin = GetChannelProvider(channel);
@@ -319,7 +332,7 @@ namespace MediaBrowser.Server.Implementations.Channels
             return list;
             return list;
         }
         }
 
 
-        private IEnumerable<MediaSourceInfo> GetCachedChannelItemMediaSources(IChannelMediaItem item)
+        private IEnumerable<MediaSourceInfo> GetCachedChannelItemMediaSources(BaseItem item)
         {
         {
             var filenamePrefix = item.Id.ToString("N");
             var filenamePrefix = item.Id.ToString("N");
             var parentPath = Path.Combine(ChannelDownloadPath, item.ChannelId);
             var parentPath = Path.Combine(ChannelDownloadPath, item.ChannelId);
@@ -368,7 +381,7 @@ namespace MediaBrowser.Server.Implementations.Channels
             return new List<MediaSourceInfo>();
             return new List<MediaSourceInfo>();
         }
         }
 
 
-        private MediaSourceInfo GetMediaSource(IChannelMediaItem item, ChannelMediaInfo info)
+        private MediaSourceInfo GetMediaSource(BaseItem item, ChannelMediaInfo info)
         {
         {
             var source = info.ToMediaSource();
             var source = info.ToMediaSource();
 
 
@@ -411,6 +424,7 @@ namespace MediaBrowser.Server.Implementations.Channels
             var parentFolderId = parentFolder.Id;
             var parentFolderId = parentFolder.Id;
 
 
             var id = GetInternalChannelId(channelInfo.Name);
             var id = GetInternalChannelId(channelInfo.Name);
+            var idString = id.ToString("N");
 
 
             var path = Channel.GetInternalMetadataPath(_config.ApplicationPaths.InternalMetadataPath, id);
             var path = Channel.GetInternalMetadataPath(_config.ApplicationPaths.InternalMetadataPath, id);
 
 
@@ -418,7 +432,6 @@ namespace MediaBrowser.Server.Implementations.Channels
             var forceUpdate = false;
             var forceUpdate = false;
 
 
             var item = _libraryManager.GetItemById(id) as Channel;
             var item = _libraryManager.GetItemById(id) as Channel;
-            var channelId = channelInfo.Name.GetMD5().ToString("N");
 
 
             if (item == null)
             if (item == null)
             {
             {
@@ -439,11 +452,11 @@ namespace MediaBrowser.Server.Implementations.Channels
             }
             }
             item.Path = path;
             item.Path = path;
 
 
-            if (!string.Equals(item.ChannelId, channelId, StringComparison.OrdinalIgnoreCase))
+            if (!string.Equals(item.ChannelId, idString, StringComparison.OrdinalIgnoreCase))
             {
             {
                 forceUpdate = true;
                 forceUpdate = true;
             }
             }
-            item.ChannelId = channelId;
+            item.ChannelId = idString;
 
 
             if (item.ParentId != parentFolderId)
             if (item.ParentId != parentFolderId)
             {
             {
@@ -492,7 +505,7 @@ namespace MediaBrowser.Server.Implementations.Channels
 
 
         public Channel GetChannel(string id)
         public Channel GetChannel(string id)
         {
         {
-            return _libraryManager.GetItemById(new Guid(id)) as Channel;
+            return _libraryManager.GetItemById(id) as Channel;
         }
         }
 
 
         public IEnumerable<ChannelFeatures> GetAllChannelFeatures()
         public IEnumerable<ChannelFeatures> GetAllChannelFeatures()
@@ -510,6 +523,11 @@ namespace MediaBrowser.Server.Implementations.Channels
 
 
         public ChannelFeatures GetChannelFeatures(string id)
         public ChannelFeatures GetChannelFeatures(string id)
         {
         {
+            if (string.IsNullOrWhiteSpace(id))
+            {
+                throw new ArgumentNullException("id");
+            }
+
             var channel = GetChannel(id);
             var channel = GetChannel(id);
             var channelProvider = GetChannelProvider(channel);
             var channelProvider = GetChannelProvider(channel);
 
 
@@ -1079,7 +1097,7 @@ namespace MediaBrowser.Server.Implementations.Channels
 
 
                 if (!string.IsNullOrWhiteSpace(folderId))
                 if (!string.IsNullOrWhiteSpace(folderId))
                 {
                 {
-                    var categoryItem = (IChannelItem)_libraryManager.GetItemById(new Guid(folderId));
+                    var categoryItem = _libraryManager.GetItemById(new Guid(folderId));
 
 
                     query.FolderId = categoryItem.ExternalId;
                     query.FolderId = categoryItem.ExternalId;
                 }
                 }
@@ -1195,7 +1213,7 @@ namespace MediaBrowser.Server.Implementations.Channels
         }
         }
 
 
         private T GetItemById<T>(string idString, string channelName, string channnelDataVersion, out bool isNew)
         private T GetItemById<T>(string idString, string channelName, string channnelDataVersion, out bool isNew)
-            where T : BaseItem, IChannelItem, new()
+            where T : BaseItem, new()
         {
         {
             var id = GetIdToHash(idString, channelName).GetMBId(typeof(T));
             var id = GetIdToHash(idString, channelName).GetMBId(typeof(T));
 
 
@@ -1233,15 +1251,48 @@ namespace MediaBrowser.Server.Implementations.Channels
 
 
             if (info.Type == ChannelItemType.Folder)
             if (info.Type == ChannelItemType.Folder)
             {
             {
-                item = GetItemById<ChannelFolderItem>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew);
+                if (info.FolderType == ChannelFolderType.MusicAlbum)
+                {
+                    item = GetItemById<MusicAlbum>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew);
+                }
+                else if (info.FolderType == ChannelFolderType.PhotoAlbum)
+                {
+                    item = GetItemById<PhotoAlbum>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew);
+                }
+                else
+                {
+                    item = GetItemById<Folder>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew);
+                }
             }
             }
             else if (info.MediaType == ChannelMediaType.Audio)
             else if (info.MediaType == ChannelMediaType.Audio)
             {
             {
-                item = GetItemById<ChannelAudioItem>(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
             else
             {
             {
-                item = GetItemById<ChannelVideoItem>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew);
+                if (info.ContentType == ChannelMediaContentType.Episode)
+                {
+                    item = GetItemById<Episode>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew);
+                }
+                else if (info.ContentType == ChannelMediaContentType.Movie)
+                {
+                    item = GetItemById<Movie>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew);
+                }
+                else if (info.ContentType == ChannelMediaContentType.Trailer || info.ExtraType == ExtraType.Trailer)
+                {
+                    item = GetItemById<Trailer>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew);
+                }
+                else
+                {
+                    item = GetItemById<Video>(info.Id, channelProvider.Name, channelProvider.DataVersion, out isNew);
+                }
             }
             }
 
 
             item.RunTimeTicks = info.RunTimeTicks;
             item.RunTimeTicks = info.RunTimeTicks;
@@ -1263,9 +1314,17 @@ namespace MediaBrowser.Server.Implementations.Channels
                 item.Tags = info.Tags;
                 item.Tags = info.Tags;
             }
             }
 
 
-            var channelItem = (IChannelItem)item;
+            var trailer = item as Trailer;
+            if (trailer != null)
+            {
+                if (!info.TrailerTypes.SequenceEqual(trailer.TrailerTypes))
+                {
+                    forceUpdate = true;
+                }
+                trailer.TrailerTypes = info.TrailerTypes;
+            }
 
 
-            channelItem.ChannelId = internalChannelId.ToString("N");
+            item.ChannelId = internalChannelId.ToString("N");
 
 
             if (item.ParentId != internalChannelId)
             if (item.ParentId != internalChannelId)
             {
             {
@@ -1273,22 +1332,29 @@ namespace MediaBrowser.Server.Implementations.Channels
             }
             }
             item.ParentId = internalChannelId;
             item.ParentId = internalChannelId;
 
 
-            if (!string.Equals(channelItem.ExternalId, info.Id, StringComparison.OrdinalIgnoreCase))
+            if (!string.Equals(item.ExternalId, info.Id, StringComparison.OrdinalIgnoreCase))
             {
             {
                 forceUpdate = true;
                 forceUpdate = true;
             }
             }
-            channelItem.ExternalId = info.Id;
+            item.ExternalId = info.Id;
 
 
-            var channelMediaItem = item as IChannelMediaItem;
-
-            if (channelMediaItem != null)
+            var channelAudioItem = item as Audio;
+            if (channelAudioItem != null)
             {
             {
-                channelMediaItem.ContentType = info.ContentType;
-                channelMediaItem.ExtraType = info.ExtraType;
-                channelMediaItem.ChannelMediaSources = info.MediaSources;
+                channelAudioItem.ExtraType = info.ExtraType;
+                channelAudioItem.ChannelMediaSources = info.MediaSources;
 
 
                 var mediaSource = info.MediaSources.FirstOrDefault();
                 var mediaSource = info.MediaSources.FirstOrDefault();
+                item.Path = mediaSource == null ? null : mediaSource.Path;
+            }
+
+            var channelVideoItem = item as Video;
+            if (channelVideoItem != null)
+            {
+                channelVideoItem.ExtraType = info.ExtraType;
+                channelVideoItem.ChannelMediaSources = info.MediaSources;
 
 
+                var mediaSource = info.MediaSources.FirstOrDefault();
                 item.Path = mediaSource == null ? null : mediaSource.Path;
                 item.Path = mediaSource == null ? null : mediaSource.Path;
             }
             }
 
 
@@ -1297,6 +1363,12 @@ namespace MediaBrowser.Server.Implementations.Channels
                 item.SetImagePath(ImageType.Primary, info.ImageUrl);
                 item.SetImagePath(ImageType.Primary, info.ImageUrl);
             }
             }
 
 
+            if (item.SourceType != SourceType.Channel)
+            {
+                item.SourceType = SourceType.Channel;
+                forceUpdate = true;
+            }
+
             if (isNew)
             if (isNew)
             {
             {
                 await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
                 await _libraryManager.CreateItem(item, cancellationToken).ConfigureAwait(false);
@@ -1334,7 +1406,12 @@ namespace MediaBrowser.Server.Implementations.Channels
 
 
         internal IChannel GetChannelProvider(Channel channel)
         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)
             if (result == null)
             {
             {
@@ -1441,7 +1518,7 @@ namespace MediaBrowser.Server.Implementations.Channels
             return await _libraryManager.GetNamedView(name, "channels", "zz_" + name, cancellationToken).ConfigureAwait(false);
             return await _libraryManager.GetNamedView(name, "channels", "zz_" + name, cancellationToken).ConfigureAwait(false);
         }
         }
 
 
-        public async Task DownloadChannelItem(IChannelMediaItem item, string destination,
+        public async Task DownloadChannelItem(BaseItem item, string destination,
             IProgress<double> progress, CancellationToken cancellationToken)
             IProgress<double> progress, CancellationToken cancellationToken)
         {
         {
             var sources = await GetDynamicMediaSources(item, cancellationToken)
             var sources = await GetDynamicMediaSources(item, cancellationToken)
@@ -1457,7 +1534,7 @@ namespace MediaBrowser.Server.Implementations.Channels
         }
         }
 
 
         private async Task TryDownloadChannelItem(MediaSourceInfo source,
         private async Task TryDownloadChannelItem(MediaSourceInfo source,
-            IChannelMediaItem item,
+            BaseItem item,
             string destination,
             string destination,
             IProgress<double> progress,
             IProgress<double> progress,
             CancellationToken cancellationToken)
             CancellationToken cancellationToken)
@@ -1469,7 +1546,6 @@ namespace MediaBrowser.Server.Implementations.Channels
                 Progress = new Progress<double>()
                 Progress = new Progress<double>()
             };
             };
 
 
-            var host = new Uri(source.Path).Host.ToLower();
             var channel = GetChannel(item.ChannelId);
             var channel = GetChannel(item.ChannelId);
             var channelProvider = GetChannelProvider(channel);
             var channelProvider = GetChannelProvider(channel);
             var features = channelProvider.GetChannelFeatures();
             var features = channelProvider.GetChannelFeatures();

+ 15 - 10
MediaBrowser.Server.Implementations/Dto/DtoService.cs

@@ -316,6 +316,11 @@ namespace MediaBrowser.Server.Implementations.Dto
                 ServerId = _appHost.SystemId
                 ServerId = _appHost.SystemId
             };
             };
 
 
+            if (item.SourceType == SourceType.Channel)
+            {
+                dto.SourceType = item.SourceType.ToString();
+            }
+
             if (fields.Contains(ItemFields.People))
             if (fields.Contains(ItemFields.People))
             {
             {
                 AttachPeople(dto, item);
                 AttachPeople(dto, item);
@@ -480,7 +485,7 @@ namespace MediaBrowser.Server.Implementations.Dto
 
 
                 var folder = (Folder)item;
                 var folder = (Folder)item;
 
 
-                if (!(folder is IChannelItem) && !(folder is Channel))
+                if (item.SourceType == SourceType.Library)
                 {
                 {
                     dto.ChildCount = GetChildCount(folder, user);
                     dto.ChildCount = GetChildCount(folder, user);
 
 
@@ -1250,6 +1255,7 @@ namespace MediaBrowser.Server.Implementations.Dto
             if (audio != null)
             if (audio != null)
             {
             {
                 dto.Album = audio.Album;
                 dto.Album = audio.Album;
+                dto.ExtraType = audio.ExtraType;
 
 
                 var albumParent = audio.AlbumEntity;
                 var albumParent = audio.AlbumEntity;
 
 
@@ -1352,6 +1358,8 @@ namespace MediaBrowser.Server.Implementations.Dto
                 {
                 {
                     dto.Chapters = GetChapterInfoDtos(item);
                     dto.Chapters = GetChapterInfoDtos(item);
                 }
                 }
+
+                dto.ExtraType = video.ExtraType;
             }
             }
 
 
             if (fields.Contains(ItemFields.MediaStreams))
             if (fields.Contains(ItemFields.MediaStreams))
@@ -1531,16 +1539,13 @@ namespace MediaBrowser.Server.Implementations.Dto
 
 
             dto.ChannelId = item.ChannelId;
             dto.ChannelId = item.ChannelId;
 
 
-            var channelItem = item as IChannelItem;
-            if (channelItem != null)
+            if (item.SourceType == SourceType.Channel && !string.IsNullOrWhiteSpace(item.ChannelId))
             {
             {
-                dto.ChannelName = _channelManagerFactory().GetChannel(channelItem.ChannelId).Name;
-            }
-
-            var channelMediaItem = item as IChannelMediaItem;
-            if (channelMediaItem != null)
-            {
-                dto.ExtraType = channelMediaItem.ExtraType;
+                var channel = _libraryManager.GetItemById(item.ChannelId);
+                if (channel != null)
+                {
+                    dto.ChannelName = channel.Name;
+                }
             }
             }
         }
         }
 
 

+ 2 - 2
MediaBrowser.Server.Implementations/EntryPoints/ActivityLogEntryPoint.cs

@@ -342,7 +342,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
 
 
         void _libraryManager_ItemRemoved(object sender, ItemChangeEventArgs e)
         void _libraryManager_ItemRemoved(object sender, ItemChangeEventArgs e)
         {
         {
-            if (e.Item is LiveTvProgram || e.Item is IChannelItem)
+            if (e.Item.SourceType != SourceType.Library)
             {
             {
                 return;
                 return;
             }
             }
@@ -356,7 +356,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
 
 
         void _libraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
         void _libraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
         {
         {
-            if (e.Item is LiveTvProgram || e.Item is IChannelItem)
+            if (e.Item.SourceType != SourceType.Library)
             {
             {
                 return;
                 return;
             }
             }

+ 1 - 1
MediaBrowser.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs

@@ -282,7 +282,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
                 return false;
                 return false;
             }
             }
 
 
-            return !(item is IChannelItem) && !(item is ILiveTvItem);
+            return item.SourceType == SourceType.Library;
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 1 - 1
MediaBrowser.Server.Implementations/EntryPoints/Notifications/Notifications.cs

@@ -346,7 +346,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
                 return false;
                 return false;
             }
             }
 
 
-            return !(item is IChannelItem) && !(item is ILiveTvItem);
+            return item.SourceType == SourceType.Library;
         }
         }
 
 
         private async void LibraryUpdateTimerCallback(object state)
         private async void LibraryUpdateTimerCallback(object state)

+ 28 - 62
MediaBrowser.Server.Implementations/Intros/DefaultIntroProvider.cs

@@ -24,17 +24,15 @@ namespace MediaBrowser.Server.Implementations.Intros
     public class DefaultIntroProvider : IIntroProvider
     public class DefaultIntroProvider : IIntroProvider
     {
     {
         private readonly ISecurityManager _security;
         private readonly ISecurityManager _security;
-        private readonly IChannelManager _channelManager;
         private readonly ILocalizationManager _localization;
         private readonly ILocalizationManager _localization;
         private readonly IConfigurationManager _serverConfig;
         private readonly IConfigurationManager _serverConfig;
         private readonly ILibraryManager _libraryManager;
         private readonly ILibraryManager _libraryManager;
         private readonly IFileSystem _fileSystem;
         private readonly IFileSystem _fileSystem;
         private readonly IMediaSourceManager _mediaSourceManager;
         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;
             _security = security;
-            _channelManager = channelManager;
             _localization = localization;
             _localization = localization;
             _serverConfig = serverConfig;
             _serverConfig = serverConfig;
             _libraryManager = libraryManager;
             _libraryManager = libraryManager;
@@ -79,76 +77,45 @@ namespace MediaBrowser.Server.Implementations.Intros
                 AppearsInItemId = item.Id
                 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>();
             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()
                     TrailerTypes = trailerTypes.ToArray()
+                });
 
 
-                }, CancellationToken.None);
-
-                candidates.AddRange(channelTrailers.Items.Select(i => new ItemWithTrailer
+                candidates.AddRange(trailerResult.Items.Select(i => new ItemWithTrailer
                 {
                 {
                     Item = i,
                     Item = i,
-                    Type = ItemWithTrailerType.ChannelTrailer,
+                    Type = i.SourceType == SourceType.Channel ? ItemWithTrailerType.ChannelTrailer : ItemWithTrailerType.ItemWithTrailer,
                     User = user,
                     User = user,
                     WatchingItem = item,
                     WatchingItem = item,
                     WatchingItemPeople = itemPeople,
                     WatchingItemPeople = itemPeople,
@@ -156,7 +123,7 @@ namespace MediaBrowser.Server.Implementations.Intros
                     Random = random,
                     Random = random,
                     LibraryManager = _libraryManager
                     LibraryManager = _libraryManager
                 }));
                 }));
-            }
+            } 
 
 
             return GetResult(item, candidates, config, ratingLevel);
             return GetResult(item, candidates, config, ratingLevel);
         }
         }
@@ -556,7 +523,6 @@ namespace MediaBrowser.Server.Implementations.Intros
 
 
         internal enum ItemWithTrailerType
         internal enum ItemWithTrailerType
         {
         {
-            LibraryTrailer,
             ChannelTrailer,
             ChannelTrailer,
             ItemWithTrailer
             ItemWithTrailer
         }
         }

+ 29 - 18
MediaBrowser.Server.Implementations/Library/LibraryManager.cs

@@ -40,8 +40,10 @@ using CommonIO;
 using MediaBrowser.Model.Extensions;
 using MediaBrowser.Model.Extensions;
 using MediaBrowser.Model.Library;
 using MediaBrowser.Model.Library;
 using MediaBrowser.Model.Net;
 using MediaBrowser.Model.Net;
+using MediaBrowser.Server.Implementations.Library.Resolvers;
 using MoreLinq;
 using MoreLinq;
 using SortOrder = MediaBrowser.Model.Entities.SortOrder;
 using SortOrder = MediaBrowser.Model.Entities.SortOrder;
+using VideoResolver = MediaBrowser.Naming.Video.VideoResolver;
 
 
 namespace MediaBrowser.Server.Implementations.Library
 namespace MediaBrowser.Server.Implementations.Library
 {
 {
@@ -347,11 +349,7 @@ namespace MediaBrowser.Server.Implementations.Library
 
 
         private void RegisterItem(Guid id, BaseItem item)
         private void RegisterItem(Guid id, BaseItem item)
         {
         {
-            if (item is LiveTvProgram)
-            {
-                return;
-            }
-            if (item is IChannelItem)
+            if (item.SourceType != SourceType.Library)
             {
             {
                 return;
                 return;
             }
             }
@@ -458,10 +456,11 @@ namespace MediaBrowser.Server.Implementations.Library
         /// Resolves the item.
         /// Resolves the item.
         /// </summary>
         /// </summary>
         /// <param name="args">The args.</param>
         /// <param name="args">The args.</param>
+        /// <param name="resolvers">The resolvers.</param>
         /// <returns>BaseItem.</returns>
         /// <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);
                 .FirstOrDefault(i => i != null);
 
 
             if (item != null)
             if (item != null)
@@ -560,10 +559,10 @@ namespace MediaBrowser.Server.Implementations.Library
         public BaseItem ResolvePath(FileSystemMetadata fileInfo,
         public BaseItem ResolvePath(FileSystemMetadata fileInfo,
             Folder parent = null)
             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)
             if (fileInfo == null)
             {
             {
@@ -619,7 +618,7 @@ namespace MediaBrowser.Server.Implementations.Library
                 return null;
                 return null;
             }
             }
 
 
-            return ResolveItem(args);
+            return ResolveItem(args, resolvers);
         }
         }
 
 
         public bool IgnoreFile(FileSystemMetadata file, BaseItem parent)
         public bool IgnoreFile(FileSystemMetadata file, BaseItem parent)
@@ -661,12 +660,19 @@ namespace MediaBrowser.Server.Implementations.Library
         }
         }
 
 
         public IEnumerable<BaseItem> ResolvePaths(IEnumerable<FileSystemMetadata> files, IDirectoryService directoryService, Folder parent, string collectionType)
         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();
             var fileList = files.Where(i => !IgnoreFile(i, parent)).ToList();
 
 
             if (parent != null)
             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);
                     var result = resolver.ResolveMultiple(parent, fileList, collectionType, directoryService);
 
 
@@ -679,22 +685,22 @@ namespace MediaBrowser.Server.Implementations.Library
                         {
                         {
                             ResolverHelper.SetInitialItemValues(item, parent, _fileSystem, this, directoryService);
                             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 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 =>
             return fileList.Select(f =>
             {
             {
                 try
                 try
                 {
                 {
-                    return ResolvePath(f, directoryService, parent, collectionType);
+                    return ResolvePath(f, directoryService, resolvers, parent, collectionType);
                 }
                 }
                 catch (Exception ex)
                 catch (Exception ex)
                 {
                 {
@@ -2310,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)));
                 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 =>
                 .Select(video =>
                 {
                 {
                     // Try to retrieve it from the db. If we don't find it, use the resolved version
                     // 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)
                     if (dbItem != null)
                     {
                     {

+ 9 - 5
MediaBrowser.Server.Implementations/Library/LocalTrailerPostScanTask.cs

@@ -28,12 +28,16 @@ namespace MediaBrowser.Server.Implementations.Library
                 .Cast<IHasTrailers>()
                 .Cast<IHasTrailers>()
                 .ToList();
                 .ToList();
 
 
-            var channelTrailerResult = await _channelManager.GetAllMediaInternal(new AllChannelMediaQuery
+            var trailerResult = _libraryManager.GetItems(new InternalItemsQuery
             {
             {
-                ExtraTypes = new[] { ExtraType.Trailer }
+                IncludeItemTypes = new[] { typeof(Trailer).Name },
+                ExcludeTrailerTypes = new[]
+                {
+                    TrailerType.LocalTrailer
+                }
 
 
-            }, CancellationToken.None);
-            var channelTrailers = channelTrailerResult.Items;
+            });
+            var trailers = trailerResult.Items;
 
 
             var numComplete = 0;
             var numComplete = 0;
 
 
@@ -41,7 +45,7 @@ namespace MediaBrowser.Server.Implementations.Library
             {
             {
                 cancellationToken.ThrowIfCancellationRequested();
                 cancellationToken.ThrowIfCancellationRequested();
 
 
-                await AssignTrailers(item, channelTrailers).ConfigureAwait(false);
+                await AssignTrailers(item, trailers).ConfigureAwait(false);
 
 
                 numComplete++;
                 numComplete++;
                 double percent = numComplete;
                 double percent = numComplete;

+ 8 - 0
MediaBrowser.Server.Implementations/Library/Resolvers/VideoResolver.cs

@@ -34,4 +34,12 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers
             get { return ResolverPriority.Last; }
             get { return ResolverPriority.Last; }
         }
         }
     }
     }
+
+    public class GenericVideoResolver<T> : BaseVideoResolver<T>
+        where T : Video, new ()
+    {
+        public GenericVideoResolver(ILibraryManager libraryManager) : base(libraryManager)
+        {
+        }
+    }
 }
 }

+ 8 - 3
MediaBrowser.Server.Implementations/Library/UserViewManager.cs

@@ -80,7 +80,7 @@ namespace MediaBrowser.Server.Implementations.Library
                     list.Add(folder);
                     list.Add(folder);
                     continue;
                     continue;
                 }
                 }
-                
+
                 if (collectionFolder != null && UserView.IsEligibleForGrouping(folder) && user.IsFolderGrouped(folder.Id))
                 if (collectionFolder != null && UserView.IsEligibleForGrouping(folder) && user.IsFolderGrouped(folder.Id))
                 {
                 {
                     groupedFolders.Add(collectionFolder);
                     groupedFolders.Add(collectionFolder);
@@ -272,7 +272,11 @@ namespace MediaBrowser.Server.Implementations.Library
                     .ToArray();
                     .ToArray();
             }
             }
 
 
-            var excludeItemTypes = includeItemTypes.Length == 0 ? new[] { "ChannelItem", "LiveTvItem", typeof(Person).Name, typeof(Studio).Name, typeof(Year).Name, typeof(GameGenre).Name, typeof(MusicGenre).Name, typeof(Genre).Name } : new string[] { };
+            var excludeItemTypes = includeItemTypes.Length == 0 ? new[]
+            {
+                typeof(Person).Name, typeof(Studio).Name, typeof(Year).Name, typeof(GameGenre).Name, typeof(MusicGenre).Name, typeof(Genre).Name
+
+            } : new string[] { };
 
 
             return _libraryManager.GetItems(new InternalItemsQuery(user)
             return _libraryManager.GetItems(new InternalItemsQuery(user)
             {
             {
@@ -282,7 +286,8 @@ namespace MediaBrowser.Server.Implementations.Library
                 IsFolder = includeItemTypes.Length == 0 ? false : (bool?)null,
                 IsFolder = includeItemTypes.Length == 0 ? false : (bool?)null,
                 ExcludeItemTypes = excludeItemTypes,
                 ExcludeItemTypes = excludeItemTypes,
                 ExcludeLocationTypes = new[] { LocationType.Virtual },
                 ExcludeLocationTypes = new[] { LocationType.Virtual },
-                Limit = limit * 20
+                Limit = limit * 20,
+                ExcludeSourceTypes = parentIds.Length == 0 ? new[] { SourceType.Channel, SourceType.LiveTV } : new SourceType[] { }
 
 
             }, parentIds);
             }, parentIds);
         }
         }

+ 1 - 1
MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs

@@ -68,7 +68,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
                     extInf = line.Substring(8).Trim();
                     extInf = line.Substring(8).Trim();
                     _logger.Info("Found m3u channel: {0}", extInf);
                     _logger.Info("Found m3u channel: {0}", extInf);
                 }
                 }
-                else if (!string.IsNullOrWhiteSpace(extInf))
+                else if (!string.IsNullOrWhiteSpace(extInf) && !line.StartsWith("#", StringComparison.OrdinalIgnoreCase))
                 {
                 {
                     var channel = GetChannelnfo(extInf, tunerHostId);
                     var channel = GetChannelnfo(extInf, tunerHostId);
                     channel.Id = channelIdPrefix + urlHash + line.GetMD5().ToString("N");
                     channel.Id = channelIdPrefix + urlHash + line.GetMD5().ToString("N");

+ 84 - 5
MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs

@@ -223,6 +223,8 @@ namespace MediaBrowser.Server.Implementations.Persistence
             _connection.AddColumn(Logger, "TypedBaseItems", "UnratedType", "Text");
             _connection.AddColumn(Logger, "TypedBaseItems", "UnratedType", "Text");
             _connection.AddColumn(Logger, "TypedBaseItems", "TopParentId", "Text");
             _connection.AddColumn(Logger, "TypedBaseItems", "TopParentId", "Text");
             _connection.AddColumn(Logger, "TypedBaseItems", "IsItemByName", "BIT");
             _connection.AddColumn(Logger, "TypedBaseItems", "IsItemByName", "BIT");
+            _connection.AddColumn(Logger, "TypedBaseItems", "SourceType", "Text");
+            _connection.AddColumn(Logger, "TypedBaseItems", "TrailerTypes", "Text");
 
 
             PrepareStatements();
             PrepareStatements();
 
 
@@ -353,7 +355,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
             "DateLastSaved",
             "DateLastSaved",
             "LockedFields",
             "LockedFields",
             "Studios",
             "Studios",
-            "Tags"
+            "Tags",
+            "SourceType",
+            "TrailerTypes"
         };
         };
 
 
         private readonly string[] _mediaStreamSaveColumns =
         private readonly string[] _mediaStreamSaveColumns =
@@ -453,7 +457,9 @@ namespace MediaBrowser.Server.Implementations.Persistence
                 "IsFolder",
                 "IsFolder",
                 "UnratedType",
                 "UnratedType",
                 "TopParentId",
                 "TopParentId",
-                "IsItemByName"
+                "IsItemByName",
+                "SourceType",
+                "TrailerTypes"
             };
             };
             _saveItemCommand = _connection.CreateCommand();
             _saveItemCommand = _connection.CreateCommand();
             _saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values (";
             _saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values (";
@@ -747,6 +753,18 @@ namespace MediaBrowser.Server.Implementations.Persistence
                     }
                     }
                     _saveItemCommand.GetParameter(index++).Value = isByName;
                     _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.Transaction = transaction;
 
 
                     _saveItemCommand.ExecuteNonQuery();
                     _saveItemCommand.ExecuteNonQuery();
@@ -1109,6 +1127,20 @@ namespace MediaBrowser.Server.Implementations.Persistence
                 item.Tags = reader.GetString(48).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
                 item.Tags = reader.GetString(48).Split('|').Where(i => !string.IsNullOrWhiteSpace(i)).ToList();
             }
             }
 
 
+            if (!reader.IsDBNull(49))
+            {
+                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;
             return item;
         }
         }
 
 
@@ -1871,6 +1903,56 @@ namespace MediaBrowser.Server.Implementations.Persistence
                 cmd.Parameters.Add(cmd, "@MaxStartDate", DbType.Date).Value = query.MaxStartDate.Value;
                 cmd.Parameters.Add(cmd, "@MaxStartDate", DbType.Date).Value = query.MaxStartDate.Value;
             }
             }
 
 
+            if (query.SourceTypes.Length == 1)
+            {
+                whereClauses.Add("SourceType=@SourceType");
+                cmd.Parameters.Add(cmd, "@SourceType", DbType.String).Value = query.SourceTypes[0];
+            }
+            else if (query.SourceTypes.Length > 1)
+            {
+                var inClause = string.Join(",", query.SourceTypes.Select(i => "'" + i + "'").ToArray());
+                whereClauses.Add(string.Format("SourceType in ({0})", inClause));
+            }
+
+            if (query.ExcludeSourceTypes.Length == 1)
+            {
+                whereClauses.Add("SourceType<>@SourceType");
+                cmd.Parameters.Add(cmd, "@SourceType", DbType.String).Value = query.SourceTypes[0];
+            }
+            else if (query.ExcludeSourceTypes.Length > 1)
+            {
+                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)
             if (query.IsAiring.HasValue)
             {
             {
                 if (query.IsAiring.Value)
                 if (query.IsAiring.Value)
@@ -2046,7 +2128,6 @@ namespace MediaBrowser.Server.Implementations.Persistence
             typeof(Trailer),
             typeof(Trailer),
             typeof(BoxSet),
             typeof(BoxSet),
             typeof(Episode),
             typeof(Episode),
-            typeof(ChannelVideoItem),
             typeof(Season),
             typeof(Season),
             typeof(Series),
             typeof(Series),
             typeof(Book),
             typeof(Book),
@@ -2152,8 +2233,6 @@ namespace MediaBrowser.Server.Implementations.Persistence
                 dict[t.Name] = new[] { t.FullName };
                 dict[t.Name] = new[] { t.FullName };
             }
             }
 
 
-            dict["ChannelItem"] = new[] { typeof(ChannelVideoItem).FullName, typeof(ChannelAudioItem).FullName, typeof(ChannelFolderItem).FullName };
-            dict["LiveTvItem"] = new[] { typeof(LiveTvAudioRecording).FullName, typeof(LiveTvVideoRecording).FullName, typeof(LiveTvChannel).FullName, typeof(LiveTvProgram).FullName };
             dict["Recording"] = new[] { typeof(LiveTvAudioRecording).FullName, typeof(LiveTvVideoRecording).FullName };
             dict["Recording"] = new[] { typeof(LiveTvAudioRecording).FullName, typeof(LiveTvVideoRecording).FullName };
             dict["Program"] = new[] { typeof(LiveTvProgram).FullName };
             dict["Program"] = new[] { typeof(LiveTvProgram).FullName };
             dict["TvChannel"] = new[] { typeof(LiveTvChannel).FullName };
             dict["TvChannel"] = new[] { typeof(LiveTvChannel).FullName };

+ 1 - 1
MediaBrowser.Server.Implementations/Sync/SyncManager.cs

@@ -536,7 +536,7 @@ namespace MediaBrowser.Server.Implementations.Sync
                     }
                     }
                 }
                 }
 
 
-                if (item is LiveTvChannel || item is IChannelItem)
+                if (item.SourceType != SourceType.Library)
                 {
                 {
                     return false;
                     return false;
                 }
                 }

+ 18 - 0
MediaBrowser.Server.Mac/Emby.Server.Mac.csproj

@@ -2957,6 +2957,18 @@
     <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\jquery\dist\jquery.slim.min.map">
     <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\jquery\dist\jquery.slim.min.map">
       <Link>Resources\dashboard-ui\bower_components\jquery\dist\jquery.slim.min.map</Link>
       <Link>Resources\dashboard-ui\bower_components\jquery\dist\jquery.slim.min.map</Link>
     </BundleResource>
     </BundleResource>
+    <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\jquery\sizzle\LICENSE.txt">
+      <Link>Resources\dashboard-ui\bower_components\jquery\sizzle\LICENSE.txt</Link>
+    </BundleResource>
+    <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\jquery\sizzle\dist\sizzle.js">
+      <Link>Resources\dashboard-ui\bower_components\jquery\sizzle\dist\sizzle.js</Link>
+    </BundleResource>
+    <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\jquery\sizzle\dist\sizzle.min.js">
+      <Link>Resources\dashboard-ui\bower_components\jquery\sizzle\dist\sizzle.min.js</Link>
+    </BundleResource>
+    <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\jquery\sizzle\dist\sizzle.min.map">
+      <Link>Resources\dashboard-ui\bower_components\jquery\sizzle\dist\sizzle.min.map</Link>
+    </BundleResource>
     <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\jquery\src\.jshintrc">
     <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\jquery\src\.jshintrc">
       <Link>Resources\dashboard-ui\bower_components\jquery\src\.jshintrc</Link>
       <Link>Resources\dashboard-ui\bower_components\jquery\src\.jshintrc</Link>
     </BundleResource>
     </BundleResource>
@@ -8690,6 +8702,9 @@
     <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\requirejs\.bower.json">
     <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\requirejs\.bower.json">
       <Link>Resources\dashboard-ui\bower_components\requirejs\.bower.json</Link>
       <Link>Resources\dashboard-ui\bower_components\requirejs\.bower.json</Link>
     </BundleResource>
     </BundleResource>
+    <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\requirejs\LICENSE">
+      <Link>Resources\dashboard-ui\bower_components\requirejs\LICENSE</Link>
+    </BundleResource>
     <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\requirejs\README.md">
     <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\bower_components\requirejs\README.md">
       <Link>Resources\dashboard-ui\bower_components\requirejs\README.md</Link>
       <Link>Resources\dashboard-ui\bower_components\requirejs\README.md</Link>
     </BundleResource>
     </BundleResource>
@@ -9812,6 +9827,9 @@
     <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\strings\fi.json">
     <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\strings\fi.json">
       <Link>Resources\dashboard-ui\strings\fi.json</Link>
       <Link>Resources\dashboard-ui\strings\fi.json</Link>
     </BundleResource>
     </BundleResource>
+    <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\strings\fr-CA.json">
+      <Link>Resources\dashboard-ui\strings\fr-CA.json</Link>
+    </BundleResource>
     <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\strings\fr.json">
     <BundleResource Include="..\MediaBrowser.WebDashboard\dashboard-ui\strings\fr.json">
       <Link>Resources\dashboard-ui\strings\fr.json</Link>
       <Link>Resources\dashboard-ui\strings\fr.json</Link>
     </BundleResource>
     </BundleResource>

Some files were not shown because too many files changed in this diff