Ver Fonte

more work on channel downloading

Luke Pulverenti há 11 anos atrás
pai
commit
c91ea99016

+ 12 - 0
MediaBrowser.Controller/Channels/ChannelVideoItem.cs

@@ -1,6 +1,7 @@
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Model.Channels;
 using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
 using System.Collections.Generic;
 using System.Globalization;
@@ -10,6 +11,8 @@ namespace MediaBrowser.Controller.Channels
 {
     public class ChannelVideoItem : Video, IChannelMediaItem
     {
+        public static IChannelManager ChannelManager { get; set; }
+
         public string ExternalId { get; set; }
 
         public string ChannelId { get; set; }
@@ -77,5 +80,14 @@ namespace MediaBrowser.Controller.Channels
                 return base.LocationType;
             }
         }
+
+        public override IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
+        {
+            var list = base.GetMediaSources(enablePathSubstitution).ToList();
+
+            list.InsertRange(0, ChannelManager.GetCachedChannelItemMediaSources(Id.ToString("N")));
+
+            return list;
+        }
     }
 }

+ 8 - 1
MediaBrowser.Controller/Channels/IChannelManager.cs

@@ -66,12 +66,19 @@ namespace MediaBrowser.Controller.Channels
         /// <returns>Task{QueryResult{BaseItemDto}}.</returns>
         Task<QueryResult<BaseItemDto>> GetChannelItems(ChannelItemQuery query, CancellationToken cancellationToken);
 
+        /// <summary>
+        /// Gets the cached channel item media sources.
+        /// </summary>
+        /// <param name="id">The identifier.</param>
+        /// <returns>IEnumerable{MediaSourceInfo}.</returns>
+        IEnumerable<MediaSourceInfo> GetCachedChannelItemMediaSources(string id);
+
         /// <summary>
         /// Gets the channel item media sources.
         /// </summary>
         /// <param name="id">The identifier.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
-        /// <returns>Task{IEnumerable{ChannelMediaInfo}}.</returns>
+        /// <returns>Task{IEnumerable{MediaSourceInfo}}.</returns>
         Task<IEnumerable<MediaSourceInfo>> GetChannelItemMediaSources(string id, CancellationToken cancellationToken);
     }
 }

+ 61 - 2
MediaBrowser.Controller/Entities/Audio/Audio.cs

@@ -1,16 +1,27 @@
-using MediaBrowser.Controller.Providers;
+using MediaBrowser.Controller.Persistence;
+using MediaBrowser.Controller.Providers;
 using MediaBrowser.Model.Configuration;
+using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Entities;
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Runtime.Serialization;
+using System.Threading;
 
 namespace MediaBrowser.Controller.Entities.Audio
 {
     /// <summary>
     /// Class Audio
     /// </summary>
-    public class Audio : BaseItem, IHasMediaStreams, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo<SongInfo>, IHasTags
+    public class Audio : BaseItem, 
+        IHasMediaStreams, 
+        IHasAlbumArtist, 
+        IHasArtist, 
+        IHasMusicGenres, 
+        IHasLookupInfo<SongInfo>, 
+        IHasTags,
+        IHasMediaSources
     {
         public string FormatName { get; set; }
         public long? Size { get; set; }
@@ -164,5 +175,53 @@ namespace MediaBrowser.Controller.Entities.Audio
 
             return info;
         }
+
+        public virtual IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
+        {
+            var result = new List<MediaSourceInfo>
+            {
+                GetVersionInfo(this, enablePathSubstitution)
+            };
+
+            return result;
+        }
+
+        private static MediaSourceInfo GetVersionInfo(Audio i, bool enablePathSubstituion)
+        {
+            var locationType = i.LocationType;
+            
+            var info = new MediaSourceInfo
+            {
+                Id = i.Id.ToString("N"),
+                LocationType = locationType,
+                MediaStreams = ItemRepository.GetMediaStreams(new MediaStreamQuery { ItemId = i.Id }).ToList(),
+                Name = i.Name,
+                Path = enablePathSubstituion ? GetMappedPath(i.Path, locationType) : i.Path,
+                RunTimeTicks = i.RunTimeTicks,
+                Container = i.Container,
+                Size = i.Size,
+                Formats = (i.FormatName ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList()
+            };
+
+            if (string.IsNullOrEmpty(info.Container))
+            {
+                if (!string.IsNullOrWhiteSpace(i.Path) && locationType != LocationType.Remote && locationType != LocationType.Virtual)
+                {
+                    info.Container = System.IO.Path.GetExtension(i.Path).TrimStart('.');
+                }
+            }
+
+            var bitrate = i.TotalBitrate ??
+                info.MediaStreams.Where(m => m.Type == MediaStreamType.Audio)
+                .Select(m => m.BitRate ?? 0)
+                .Sum();
+
+            if (bitrate > 0)
+            {
+                info.Bitrate = bitrate;
+            }
+
+            return info;
+        }
     }
 }

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

@@ -1549,5 +1549,18 @@ namespace MediaBrowser.Controller.Entities
 
             return hasChanges;
         }
+
+        protected static string GetMappedPath(string path, LocationType locationType)
+        {
+            if (locationType == LocationType.FileSystem || locationType == LocationType.Offline)
+            {
+                foreach (var map in ConfigurationManager.Configuration.PathSubstitutions)
+                {
+                    path = FileSystem.SubstitutePath(path, map.From, map.To);
+                }
+            }
+
+            return path;
+        }
     }
 }

+ 15 - 0
MediaBrowser.Controller/Entities/IHasMediaSources.cs

@@ -0,0 +1,15 @@
+using MediaBrowser.Model.Dto;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Controller.Entities
+{
+    public interface IHasMediaSources
+    {
+        /// <summary>
+        /// Gets the media sources.
+        /// </summary>
+        /// <param name="enablePathSubstitution">if set to <c>true</c> [enable path substitution].</param>
+        /// <returns>Task{IEnumerable{MediaSourceInfo}}.</returns>
+        IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution);
+    }
+}

+ 183 - 1
MediaBrowser.Controller/Entities/Video.cs

@@ -2,6 +2,7 @@
 using MediaBrowser.Controller.Persistence;
 using MediaBrowser.Controller.Providers;
 using MediaBrowser.Controller.Resolvers;
+using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.MediaInfo;
 using System;
@@ -18,7 +19,12 @@ namespace MediaBrowser.Controller.Entities
     /// <summary>
     /// Class Video
     /// </summary>
-    public class Video : BaseItem, IHasMediaStreams, IHasAspectRatio, IHasTags, ISupportsPlaceHolders
+    public class Video : BaseItem, 
+        IHasMediaStreams, 
+        IHasAspectRatio, 
+        IHasTags, 
+        ISupportsPlaceHolders,
+        IHasMediaSources
     {
         public bool IsMultiPart { get; set; }
         public bool HasLocalAlternateVersions { get; set; }
@@ -504,5 +510,181 @@ namespace MediaBrowser.Controller.Entities
 
             }).FirstOrDefault();
         }
+
+        public virtual IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
+        {
+            var item = this;
+
+            var result = item.GetAlternateVersions()
+                .Select(i => GetVersionInfo(enablePathSubstitution, i, MediaSourceType.Grouping))
+                .ToList();
+
+            result.Add(GetVersionInfo(enablePathSubstitution, item, MediaSourceType.Default));
+
+            return result.OrderBy(i =>
+            {
+                if (item.VideoType == VideoType.VideoFile)
+                {
+                    return 0;
+                }
+
+                return 1;
+
+            }).ThenBy(i => i.Video3DFormat.HasValue ? 1 : 0)
+            .ThenByDescending(i =>
+            {
+                var stream = i.VideoStream;
+
+                return stream == null || stream.Width == null ? 0 : stream.Width.Value;
+            })
+            .ToList();
+        }
+
+        private static MediaSourceInfo GetVersionInfo(bool enablePathSubstitution, Video i, MediaSourceType type)
+        {
+            var mediaStreams = ItemRepository.GetMediaStreams(new MediaStreamQuery { ItemId = i.Id }).ToList();
+
+            var locationType = i.LocationType;
+            
+            var info = new MediaSourceInfo
+            {
+                Id = i.Id.ToString("N"),
+                IsoType = i.IsoType,
+                LocationType = locationType,
+                MediaStreams = mediaStreams,
+                Name = GetMediaSourceName(i, mediaStreams),
+                Path = enablePathSubstitution ? GetMappedPath(i.Path, locationType) : i.Path,
+                RunTimeTicks = i.RunTimeTicks,
+                Video3DFormat = i.Video3DFormat,
+                VideoType = i.VideoType,
+                Container = i.Container,
+                Size = i.Size,
+                Formats = (i.FormatName ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(),
+                Timestamp = i.Timestamp,
+                Type = type
+            };
+
+            if (string.IsNullOrEmpty(info.Container))
+            {
+                if (i.VideoType == VideoType.VideoFile || i.VideoType == VideoType.Iso)
+                {
+                    if (!string.IsNullOrWhiteSpace(i.Path) && locationType != LocationType.Remote && locationType != LocationType.Virtual)
+                    {
+                        info.Container = System.IO.Path.GetExtension(i.Path).TrimStart('.');
+                    }
+                }
+            }
+
+            try
+            {
+                var bitrate = i.TotalBitrate ??
+                    info.MediaStreams.Where(m => m.Type != MediaStreamType.Subtitle && !string.Equals(m.Codec, "mjpeg", StringComparison.OrdinalIgnoreCase))
+                    .Select(m => m.BitRate ?? 0)
+                    .Sum();
+
+                if (bitrate > 0)
+                {
+                    info.Bitrate = bitrate;
+                }
+            }
+            catch (OverflowException ex)
+            {
+                Logger.ErrorException("Error calculating total bitrate", ex);
+            }
+
+            return info;
+        }
+
+
+        private static string GetMediaSourceName(Video video, List<MediaStream> mediaStreams)
+        {
+            var terms = new List<string>();
+
+            var videoStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
+            var audioStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio);
+
+            if (video.Video3DFormat.HasValue)
+            {
+                terms.Add("3D");
+            }
+
+            if (video.VideoType == VideoType.BluRay)
+            {
+                terms.Add("Bluray");
+            }
+            else if (video.VideoType == VideoType.Dvd)
+            {
+                terms.Add("DVD");
+            }
+            else if (video.VideoType == VideoType.HdDvd)
+            {
+                terms.Add("HD-DVD");
+            }
+            else if (video.VideoType == VideoType.Iso)
+            {
+                if (video.IsoType.HasValue)
+                {
+                    if (video.IsoType.Value == Model.Entities.IsoType.BluRay)
+                    {
+                        terms.Add("Bluray");
+                    }
+                    else if (video.IsoType.Value == Model.Entities.IsoType.Dvd)
+                    {
+                        terms.Add("DVD");
+                    }
+                }
+                else
+                {
+                    terms.Add("ISO");
+                }
+            }
+
+            if (videoStream != null)
+            {
+                if (videoStream.Width.HasValue)
+                {
+                    if (videoStream.Width.Value >= 3800)
+                    {
+                        terms.Add("4K");
+                    }
+                    else if (videoStream.Width.Value >= 1900)
+                    {
+                        terms.Add("1080P");
+                    }
+                    else if (videoStream.Width.Value >= 1270)
+                    {
+                        terms.Add("720P");
+                    }
+                    else if (videoStream.Width.Value >= 700)
+                    {
+                        terms.Add("480P");
+                    }
+                    else
+                    {
+                        terms.Add("SD");
+                    }
+                }
+            }
+
+            if (videoStream != null && !string.IsNullOrWhiteSpace(videoStream.Codec))
+            {
+                terms.Add(videoStream.Codec.ToUpper());
+            }
+
+            if (audioStream != null)
+            {
+                var audioCodec = string.Equals(audioStream.Codec, "dca", StringComparison.OrdinalIgnoreCase)
+                    ? audioStream.Profile
+                    : audioStream.Codec;
+
+                if (!string.IsNullOrEmpty(audioCodec))
+                {
+                    terms.Add(audioCodec.ToUpper());
+                }
+            }
+
+            return string.Join("/", terms.ToArray());
+        }
+
     }
 }

+ 1 - 0
MediaBrowser.Controller/MediaBrowser.Controller.csproj

@@ -120,6 +120,7 @@
     <Compile Include="Entities\IHasDisplayOrder.cs" />
     <Compile Include="Entities\IHasImages.cs" />
     <Compile Include="Entities\IHasKeywords.cs" />
+    <Compile Include="Entities\IHasMediaSources.cs" />
     <Compile Include="Entities\IHasMediaStreams.cs" />
     <Compile Include="Entities\IHasMetascore.cs" />
     <Compile Include="Entities\IHasPreferredMetadataLanguage.cs" />

+ 9 - 0
MediaBrowser.Model/Dto/MediaSourceInfo.cs

@@ -12,6 +12,8 @@ namespace MediaBrowser.Model.Dto
 
         public string Path { get; set; }
 
+        public MediaSourceType Type { get; set; }
+
         public string Container { get; set; }
         public long? Size { get; set; }
 
@@ -101,4 +103,11 @@ namespace MediaBrowser.Model.Dto
             }
         }
     }
+
+    public enum MediaSourceType
+    {
+        Default = 0,
+        Grouping = 1,
+        Cache = 2
+    }
 }

+ 1 - 1
MediaBrowser.Providers/Savers/XmlSaverHelpers.cs

@@ -649,7 +649,7 @@ namespace MediaBrowser.Providers.Savers
         /// </summary>
         /// <typeparam name="T"></typeparam>
         public static void AddMediaInfo<T>(T item, StringBuilder builder, IItemRepository itemRepository)
-            where T : BaseItem, IHasMediaStreams
+            where T : BaseItem
         {
             var video = item as Video;
 

+ 9 - 6
MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs

@@ -134,7 +134,7 @@ namespace MediaBrowser.Server.Implementations.Channels
 
             if (cachedVersions.Count > 0)
             {
-                await RefreshMediaSourceItems(cachedVersions, item.IsVideo, cancellationToken).ConfigureAwait(false);
+                await RefreshMediaSourceItems(cachedVersions, cancellationToken).ConfigureAwait(false);
                 return;
             }
 
@@ -152,7 +152,7 @@ namespace MediaBrowser.Server.Implementations.Channels
                 options.RequestHeaders[header.Key] = header.Value;
             }
 
-            var destination = Path.Combine(path, item.ChannelId, source.Path.GetMD5().ToString("N"));
+            var destination = Path.Combine(path, item.ChannelId, item.Id);
             Directory.CreateDirectory(Path.GetDirectoryName(destination));
 
             // Determine output extension
@@ -180,23 +180,26 @@ namespace MediaBrowser.Server.Implementations.Channels
 
             File.Move(response.TempFilePath, destination);
 
-            await RefreshMediaSourceItem(destination, item.IsVideo, cancellationToken).ConfigureAwait(false);
+            await RefreshMediaSourceItem(destination, cancellationToken).ConfigureAwait(false);
         }
 
-        private async Task RefreshMediaSourceItems(IEnumerable<MediaSourceInfo> items, bool isVideo, CancellationToken cancellationToken)
+        private async Task RefreshMediaSourceItems(IEnumerable<MediaSourceInfo> items, CancellationToken cancellationToken)
         {
             foreach (var item in items)
             {
-                await RefreshMediaSourceItem(item.Path, isVideo, cancellationToken).ConfigureAwait(false);
+                await RefreshMediaSourceItem(item.Path, cancellationToken).ConfigureAwait(false);
             }
         }
 
-        private async Task RefreshMediaSourceItem(string path, bool isVideo, CancellationToken cancellationToken)
+        private async Task RefreshMediaSourceItem(string path, CancellationToken cancellationToken)
         {
             var item = _libraryManager.ResolvePath(new FileInfo(path));
 
             if (item != null)
             {
+                // Get the version from the database
+                item = _libraryManager.GetItemById(item.Id) ?? item;
+
                 await item.RefreshMetadata(cancellationToken).ConfigureAwait(false);
             }
         }

+ 59 - 47
MediaBrowser.Server.Implementations/Channels/ChannelManager.cs

@@ -6,6 +6,7 @@ using MediaBrowser.Controller.Dto;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Providers;
+using MediaBrowser.Controller.Resolvers;
 using MediaBrowser.Model.Channels;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
@@ -194,77 +195,88 @@ namespace MediaBrowser.Server.Implementations.Channels
             var sources = SortMediaInfoResults(results).Select(i => GetMediaSource(item, i))
                 .ToList();
 
-            var channelIdString = channel.Id.ToString("N");
-            var isVideo = string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase);
+            var cachedVersions = GetCachedChannelItemMediaSources(item);
 
-            var cachedVersionTasks = sources
-                .Select(i => GetCachedVersion(channelIdString, i, isVideo, cancellationToken));
-
-            var cachedVersions = await Task.WhenAll(cachedVersionTasks).ConfigureAwait(false);
-
-            sources.InsertRange(0, cachedVersions.Where(i => i != null));
+            sources.InsertRange(0, cachedVersions);
 
             return sources;
         }
 
-        private MediaSourceInfo GetMediaSource(IChannelMediaItem item, ChannelMediaInfo info)
+        public IEnumerable<MediaSourceInfo> GetCachedChannelItemMediaSources(string id)
         {
-            var id = info.Path.GetMD5().ToString("N");
-
-            var source = new MediaSourceInfo
-            {
-                MediaStreams = GetMediaStreams(info).ToList(),
-
-                Container = info.Container,
-                LocationType = info.IsRemote ? LocationType.Remote : LocationType.FileSystem,
-                Path = info.Path,
-                RequiredHttpHeaders = info.RequiredHttpHeaders,
-                RunTimeTicks = item.RunTimeTicks,
-                Name = id,
-                Id = id
-            };
+            var item = (IChannelMediaItem)_libraryManager.GetItemById(id);
 
-            return source;
+            return GetCachedChannelItemMediaSources(item);
         }
 
-        private async Task<MediaSourceInfo> GetCachedVersion(string channelId, 
-            MediaSourceInfo info, 
-            bool isVideo,
-            CancellationToken cancellationToken)
+        public IEnumerable<MediaSourceInfo> GetCachedChannelItemMediaSources(IChannelMediaItem item)
         {
-            var filename = info.Path.GetMD5().ToString("N");
-
-            var path = Path.Combine(ChannelDownloadPath, channelId, filename);
+            var filenamePrefix = item.Id.ToString("N");
+            var parentPath = Path.Combine(ChannelDownloadPath, item.ChannelId);
 
             try
             {
-                var file = Directory.EnumerateFiles(Path.GetDirectoryName(path), "*", SearchOption.TopDirectoryOnly)
-                        .FirstOrDefault(i => (Path.GetFileName(i) ?? string.Empty).StartsWith(filename, StringComparison.OrdinalIgnoreCase));
+                var files = new DirectoryInfo(parentPath).EnumerateFiles("*", SearchOption.TopDirectoryOnly);
 
-                if (!string.IsNullOrWhiteSpace(file))
+                if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase))
                 {
-                    var source = new MediaSourceInfo
-                    {
-                        Path = file,
-                        LocationType = LocationType.FileSystem,
-                        Name = "Cached " + info.Name,
-                        Id = file.GetMD5().ToString("N")
-                    };
+                    files = files.Where(i => EntityResolutionHelper.IsVideoFile(i.FullName));
+                }
+                else
+                {
+                    files = files.Where(i => EntityResolutionHelper.IsAudioFile(i.FullName));
+                }
+
+                var file = files
+                    .FirstOrDefault(i => i.Name.StartsWith(filenamePrefix, StringComparison.OrdinalIgnoreCase));
+
+                if (file != null)
+                {
+                    var cachedItem = _libraryManager.ResolvePath(file);
 
-                    if (isVideo)
+                    if (cachedItem != null)
                     {
-                        source.VideoType = VideoType.VideoFile;
-                    }
+                        var hasMediaSources = _libraryManager.GetItemById(cachedItem.Id) as IHasMediaSources;
+
+                        if (hasMediaSources != null)
+                        {
+                            var source = hasMediaSources.GetMediaSources(true).FirstOrDefault();
 
-                    return source;
+                            if (source != null)
+                            {
+                                source.Type = MediaSourceType.Cache;
+                                return new[] { source };
+                            }
+                        }
+                    }
                 }
             }
             catch (DirectoryNotFoundException)
             {
-                return null;
+
             }
 
-            return null;
+            return new List<MediaSourceInfo>();
+        }
+
+        private MediaSourceInfo GetMediaSource(IChannelMediaItem item, ChannelMediaInfo info)
+        {
+            var id = info.Path.GetMD5().ToString("N");
+
+            var source = new MediaSourceInfo
+            {
+                MediaStreams = GetMediaStreams(info).ToList(),
+
+                Container = info.Container,
+                LocationType = info.IsRemote ? LocationType.Remote : LocationType.FileSystem,
+                Path = info.Path,
+                RequiredHttpHeaders = info.RequiredHttpHeaders,
+                RunTimeTicks = item.RunTimeTicks,
+                Name = id,
+                Id = id
+            };
+
+            return source;
         }
 
         private IEnumerable<MediaStream> GetMediaStreams(ChannelMediaInfo info)

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

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Extensions;
+using System.Threading;
+using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Controller.Channels;
 using MediaBrowser.Controller.Configuration;
@@ -919,8 +920,12 @@ namespace MediaBrowser.Server.Implementations.Dto
                     dto.AlbumPrimaryImageTag = GetImageCacheTag(albumParent, ImageType.Primary);
                 }
 
-                dto.MediaSources = GetAudioMediaSources(audio);
                 dto.MediaSourceCount = 1;
+
+                if (fields.Contains(ItemFields.MediaSources))
+                {
+                    dto.MediaSources = GetMediaSources(audio);
+                }
             }
 
             var album = item as MusicAlbum;
@@ -955,7 +960,7 @@ namespace MediaBrowser.Server.Implementations.Dto
 
                 if (fields.Contains(ItemFields.MediaSources))
                 {
-                    dto.MediaSources = GetVideoMediaSources(video);
+                    dto.MediaSources = GetMediaSources(video);
                 }
 
                 if (fields.Contains(ItemFields.Chapters))
@@ -1144,14 +1149,14 @@ namespace MediaBrowser.Server.Implementations.Dto
 
             if (video != null)
             {
-                return GetVideoMediaSources(video);
+                return video.GetMediaSources(true).ToList();
             }
 
             var audio = item as Audio;
 
             if (audio != null)
             {
-                return GetAudioMediaSources(audio);
+                return audio.GetMediaSources(true).ToList();
             }
 
             var result = new List<MediaSourceInfo>
@@ -1175,131 +1180,6 @@ namespace MediaBrowser.Server.Implementations.Dto
             return result;
         }
 
-        private List<MediaSourceInfo> GetVideoMediaSources(Video item)
-        {
-            var result = item.GetAlternateVersions().Select(GetVersionInfo).ToList();
-
-            result.Add(GetVersionInfo(item));
-
-            return result.OrderBy(i =>
-            {
-                if (item.VideoType == VideoType.VideoFile)
-                {
-                    return 0;
-                }
-
-                return 1;
-
-            }).ThenBy(i => i.Video3DFormat.HasValue ? 1 : 0)
-            .ThenByDescending(i =>
-            {
-                var stream = i.VideoStream;
-
-                return stream == null || stream.Width == null ? 0 : stream.Width.Value;
-            })
-            .ToList();
-        }
-
-        private List<MediaSourceInfo> GetAudioMediaSources(Audio item)
-        {
-            var result = new List<MediaSourceInfo>
-            {
-                GetVersionInfo(item)
-            };
-
-            return result;
-        }
-
-        private MediaSourceInfo GetVersionInfo(Video i)
-        {
-            var mediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery { ItemId = i.Id }).ToList();
-
-            var info = new MediaSourceInfo
-            {
-                Id = i.Id.ToString("N"),
-                IsoType = i.IsoType,
-                LocationType = i.LocationType,
-                MediaStreams = mediaStreams,
-                Name = GetMediaSourceName(i, mediaStreams),
-                Path = GetMappedPath(i),
-                RunTimeTicks = i.RunTimeTicks,
-                Video3DFormat = i.Video3DFormat,
-                VideoType = i.VideoType,
-                Container = i.Container,
-                Size = i.Size,
-                Formats = (i.FormatName ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList(),
-                Timestamp = i.Timestamp
-            };
-
-            if (string.IsNullOrEmpty(info.Container))
-            {
-                if (i.VideoType == VideoType.VideoFile || i.VideoType == VideoType.Iso)
-                {
-                    var locationType = i.LocationType;
-                    if (!string.IsNullOrWhiteSpace(i.Path) && locationType != LocationType.Remote && locationType != LocationType.Virtual)
-                    {
-                        info.Container = Path.GetExtension(i.Path).TrimStart('.');
-                    }
-                }
-            }
-
-            try
-            {
-                var bitrate = i.TotalBitrate ??
-                    info.MediaStreams.Where(m => m.Type != MediaStreamType.Subtitle && !string.Equals(m.Codec, "mjpeg", StringComparison.OrdinalIgnoreCase))
-                    .Select(m => m.BitRate ?? 0)
-                    .Sum();
-
-                if (bitrate > 0)
-                {
-                    info.Bitrate = bitrate;
-                }
-            }
-            catch (OverflowException ex)
-            {
-                _logger.ErrorException("Error calculating total bitrate", ex);
-            }
-
-            return info;
-        }
-
-        private MediaSourceInfo GetVersionInfo(Audio i)
-        {
-            var info = new MediaSourceInfo
-            {
-                Id = i.Id.ToString("N"),
-                LocationType = i.LocationType,
-                MediaStreams = _itemRepo.GetMediaStreams(new MediaStreamQuery { ItemId = i.Id }).ToList(),
-                Name = i.Name,
-                Path = GetMappedPath(i),
-                RunTimeTicks = i.RunTimeTicks,
-                Container = i.Container,
-                Size = i.Size,
-                Formats = (i.FormatName ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList()
-            };
-
-            if (string.IsNullOrEmpty(info.Container))
-            {
-                var locationType = i.LocationType;
-                if (!string.IsNullOrWhiteSpace(i.Path) && locationType != LocationType.Remote && locationType != LocationType.Virtual)
-                {
-                    info.Container = Path.GetExtension(i.Path).TrimStart('.');
-                }
-            }
-
-            var bitrate = i.TotalBitrate ??
-                info.MediaStreams.Where(m => m.Type == MediaStreamType.Audio)
-                .Select(m => m.BitRate ?? 0)
-                .Sum();
-
-            if (bitrate > 0)
-            {
-                info.Bitrate = bitrate;
-            }
-
-            return info;
-        }
-
         private string GetMappedPath(IHasMetadata item)
         {
             var path = item.Path;
@@ -1317,96 +1197,6 @@ namespace MediaBrowser.Server.Implementations.Dto
             return path;
         }
 
-        private string GetMediaSourceName(Video video, List<MediaStream> mediaStreams)
-        {
-            var terms = new List<string>();
-
-            var videoStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Video);
-            var audioStream = mediaStreams.FirstOrDefault(i => i.Type == MediaStreamType.Audio);
-
-            if (video.Video3DFormat.HasValue)
-            {
-                terms.Add("3D");
-            }
-
-            if (video.VideoType == VideoType.BluRay)
-            {
-                terms.Add("Bluray");
-            }
-            else if (video.VideoType == VideoType.Dvd)
-            {
-                terms.Add("DVD");
-            }
-            else if (video.VideoType == VideoType.HdDvd)
-            {
-                terms.Add("HD-DVD");
-            }
-            else if (video.VideoType == VideoType.Iso)
-            {
-                if (video.IsoType.HasValue)
-                {
-                    if (video.IsoType.Value == IsoType.BluRay)
-                    {
-                        terms.Add("Bluray");
-                    }
-                    else if (video.IsoType.Value == IsoType.Dvd)
-                    {
-                        terms.Add("DVD");
-                    }
-                }
-                else
-                {
-                    terms.Add("ISO");
-                }
-            }
-
-            if (videoStream != null)
-            {
-                if (videoStream.Width.HasValue)
-                {
-                    if (videoStream.Width.Value >= 3800)
-                    {
-                        terms.Add("4K");
-                    }
-                    else if (videoStream.Width.Value >= 1900)
-                    {
-                        terms.Add("1080P");
-                    }
-                    else if (videoStream.Width.Value >= 1270)
-                    {
-                        terms.Add("720P");
-                    }
-                    else if (videoStream.Width.Value >= 700)
-                    {
-                        terms.Add("480P");
-                    }
-                    else
-                    {
-                        terms.Add("SD");
-                    }
-                }
-            }
-
-            if (videoStream != null && !string.IsNullOrWhiteSpace(videoStream.Codec))
-            {
-                terms.Add(videoStream.Codec.ToUpper());
-            }
-
-            if (audioStream != null)
-            {
-                var audioCodec = string.Equals(audioStream.Codec, "dca", StringComparison.OrdinalIgnoreCase)
-                    ? audioStream.Profile
-                    : audioStream.Codec;
-
-                if (!string.IsNullOrEmpty(audioCodec))
-                {
-                    terms.Add(audioCodec.ToUpper());
-                }
-            }
-
-            return string.Join("/", terms.ToArray());
-        }
-
         private void SetProductionLocations(BaseItem item, BaseItemDto dto)
         {
             var hasProductionLocations = item as IHasProductionLocations;

+ 2 - 1
MediaBrowser.Server.Implementations/Localization/Server/server.json

@@ -806,5 +806,6 @@
 	"LabelChannelDownloadPath": "Channel content download path:",
 	"LabelChannelDownloadPathHelp": "Specify a custom download path if desired. Leave empty to download to an internal program data folder.",
 	"LabelChannelDownloadAge": "Delete content after: (days)",
-	"LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming."
+	"LabelChannelDownloadAgeHelp": "Downloaded content older than this will be deleted. It will remain playable via internet streaming.",
+	"ChannelSettingsFormHelp": "Install channels such as Trailers and Vimeo in the plugin catalog."
 }

+ 1 - 0
MediaBrowser.ServerApplication/ApplicationHost.cs

@@ -680,6 +680,7 @@ namespace MediaBrowser.ServerApplication
             Folder.UserManager = UserManager;
             BaseItem.FileSystem = FileSystemManager;
             BaseItem.UserDataManager = UserDataManager;
+            ChannelVideoItem.ChannelManager = ChannelManager;
         }
 
         /// <summary>