diff --git a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs b/MediaBrowser.Controller/Channels/ChannelVideoItem.cs index 2f207c420..7a261bc58 100644 --- a/MediaBrowser.Controller/Channels/ChannelVideoItem.cs +++ b/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 GetMediaSources(bool enablePathSubstitution) + { + var list = base.GetMediaSources(enablePathSubstitution).ToList(); + + list.InsertRange(0, ChannelManager.GetCachedChannelItemMediaSources(Id.ToString("N"))); + + return list; + } } } diff --git a/MediaBrowser.Controller/Channels/IChannelManager.cs b/MediaBrowser.Controller/Channels/IChannelManager.cs index 4be38870b..180ac4a39 100644 --- a/MediaBrowser.Controller/Channels/IChannelManager.cs +++ b/MediaBrowser.Controller/Channels/IChannelManager.cs @@ -66,12 +66,19 @@ namespace MediaBrowser.Controller.Channels /// Task{QueryResult{BaseItemDto}}. Task> GetChannelItems(ChannelItemQuery query, CancellationToken cancellationToken); + /// + /// Gets the cached channel item media sources. + /// + /// The identifier. + /// IEnumerable{MediaSourceInfo}. + IEnumerable GetCachedChannelItemMediaSources(string id); + /// /// Gets the channel item media sources. /// /// The identifier. /// The cancellation token. - /// Task{IEnumerable{ChannelMediaInfo}}. + /// Task{IEnumerable{MediaSourceInfo}}. Task> GetChannelItemMediaSources(string id, CancellationToken cancellationToken); } } diff --git a/MediaBrowser.Controller/Entities/Audio/Audio.cs b/MediaBrowser.Controller/Entities/Audio/Audio.cs index dca645a75..43de1f5b0 100644 --- a/MediaBrowser.Controller/Entities/Audio/Audio.cs +++ b/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 { /// /// Class Audio /// - public class Audio : BaseItem, IHasMediaStreams, IHasAlbumArtist, IHasArtist, IHasMusicGenres, IHasLookupInfo, IHasTags + public class Audio : BaseItem, + IHasMediaStreams, + IHasAlbumArtist, + IHasArtist, + IHasMusicGenres, + IHasLookupInfo, + 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 GetMediaSources(bool enablePathSubstitution) + { + var result = new List + { + 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; + } } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 52c6e951e..b7edbfc60 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/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; + } } } diff --git a/MediaBrowser.Controller/Entities/IHasMediaSources.cs b/MediaBrowser.Controller/Entities/IHasMediaSources.cs new file mode 100644 index 000000000..0b0dd1bf8 --- /dev/null +++ b/MediaBrowser.Controller/Entities/IHasMediaSources.cs @@ -0,0 +1,15 @@ +using MediaBrowser.Model.Dto; +using System.Collections.Generic; + +namespace MediaBrowser.Controller.Entities +{ + public interface IHasMediaSources + { + /// + /// Gets the media sources. + /// + /// if set to true [enable path substitution]. + /// Task{IEnumerable{MediaSourceInfo}}. + IEnumerable GetMediaSources(bool enablePathSubstitution); + } +} diff --git a/MediaBrowser.Controller/Entities/Video.cs b/MediaBrowser.Controller/Entities/Video.cs index 9570faa73..3bc08506e 100644 --- a/MediaBrowser.Controller/Entities/Video.cs +++ b/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 /// /// Class Video /// - 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 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 mediaStreams) + { + var terms = new List(); + + 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()); + } + } } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 435eb9c0c..1d3c007a7 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -120,6 +120,7 @@ + diff --git a/MediaBrowser.Model/Dto/MediaSourceInfo.cs b/MediaBrowser.Model/Dto/MediaSourceInfo.cs index 598eacc21..eb1ea7287 100644 --- a/MediaBrowser.Model/Dto/MediaSourceInfo.cs +++ b/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 + } } diff --git a/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs b/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs index 7241dedca..6b51c62f9 100644 --- a/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs +++ b/MediaBrowser.Providers/Savers/XmlSaverHelpers.cs @@ -649,7 +649,7 @@ namespace MediaBrowser.Providers.Savers /// /// public static void AddMediaInfo(T item, StringBuilder builder, IItemRepository itemRepository) - where T : BaseItem, IHasMediaStreams + where T : BaseItem { var video = item as Video; diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs b/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs index 21b5ba6da..28f7352c5 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelDownloadScheduledTask.cs +++ b/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 items, bool isVideo, CancellationToken cancellationToken) + private async Task RefreshMediaSourceItems(IEnumerable 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); } } diff --git a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs b/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs index b9e4e73b0..9f4db175e 100644 --- a/MediaBrowser.Server.Implementations/Channels/ChannelManager.cs +++ b/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,19 +195,70 @@ 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; } + public IEnumerable GetCachedChannelItemMediaSources(string id) + { + var item = (IChannelMediaItem)_libraryManager.GetItemById(id); + + return GetCachedChannelItemMediaSources(item); + } + + public IEnumerable GetCachedChannelItemMediaSources(IChannelMediaItem item) + { + var filenamePrefix = item.Id.ToString("N"); + var parentPath = Path.Combine(ChannelDownloadPath, item.ChannelId); + + try + { + var files = new DirectoryInfo(parentPath).EnumerateFiles("*", SearchOption.TopDirectoryOnly); + + if (string.Equals(item.MediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase)) + { + 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 (cachedItem != null) + { + var hasMediaSources = _libraryManager.GetItemById(cachedItem.Id) as IHasMediaSources; + + if (hasMediaSources != null) + { + var source = hasMediaSources.GetMediaSources(true).FirstOrDefault(); + + if (source != null) + { + source.Type = MediaSourceType.Cache; + return new[] { source }; + } + } + } + } + } + catch (DirectoryNotFoundException) + { + + } + + return new List(); + } + private MediaSourceInfo GetMediaSource(IChannelMediaItem item, ChannelMediaInfo info) { var id = info.Path.GetMD5().ToString("N"); @@ -227,46 +279,6 @@ namespace MediaBrowser.Server.Implementations.Channels return source; } - private async Task GetCachedVersion(string channelId, - MediaSourceInfo info, - bool isVideo, - CancellationToken cancellationToken) - { - var filename = info.Path.GetMD5().ToString("N"); - - var path = Path.Combine(ChannelDownloadPath, channelId, filename); - - try - { - var file = Directory.EnumerateFiles(Path.GetDirectoryName(path), "*", SearchOption.TopDirectoryOnly) - .FirstOrDefault(i => (Path.GetFileName(i) ?? string.Empty).StartsWith(filename, StringComparison.OrdinalIgnoreCase)); - - if (!string.IsNullOrWhiteSpace(file)) - { - var source = new MediaSourceInfo - { - Path = file, - LocationType = LocationType.FileSystem, - Name = "Cached " + info.Name, - Id = file.GetMD5().ToString("N") - }; - - if (isVideo) - { - source.VideoType = VideoType.VideoFile; - } - - return source; - } - } - catch (DirectoryNotFoundException) - { - return null; - } - - return null; - } - private IEnumerable GetMediaStreams(ChannelMediaInfo info) { var list = new List(); diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 520ffd417..2296edcef 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/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 @@ -1175,131 +1180,6 @@ namespace MediaBrowser.Server.Implementations.Dto return result; } - private List 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 GetAudioMediaSources(Audio item) - { - var result = new List - { - 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 mediaStreams) - { - var terms = new List(); - - 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; diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index d7c923b58..d7b2a1556 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/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." } \ No newline at end of file diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index dec5980c9..868a72b08 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -680,6 +680,7 @@ namespace MediaBrowser.ServerApplication Folder.UserManager = UserManager; BaseItem.FileSystem = FileSystemManager; BaseItem.UserDataManager = UserDataManager; + ChannelVideoItem.ChannelManager = ChannelManager; } ///