diff options
18 files changed, 428 insertions, 338 deletions
diff --git a/MediaBrowser.Common/Kernel/BaseKernel.cs b/MediaBrowser.Common/Kernel/BaseKernel.cs index 088acbedd..a4a1d5b4d 100644 --- a/MediaBrowser.Common/Kernel/BaseKernel.cs +++ b/MediaBrowser.Common/Kernel/BaseKernel.cs @@ -483,8 +483,7 @@ namespace MediaBrowser.Common.Kernel CompositionContainer = MefUtils.GetSafeCompositionContainer(Assemblies.Select(i => new AssemblyCatalog(i))); - CompositionContainer.ComposeExportedValue("kernel", this); - CompositionContainer.ComposeExportedValue("logger", Logging.LogManager.GetLogger("App")); + ComposeExportedValues(CompositionContainer); CompositionContainer.ComposeParts(this); @@ -494,6 +493,15 @@ namespace MediaBrowser.Common.Kernel } /// <summary> + /// Composes the exported values. + /// </summary> + /// <param name="container">The container.</param> + protected virtual void ComposeExportedValues(CompositionContainer container) + { + container.ComposeExportedValue("logger", Logging.LogManager.GetLogger("App")); + } + + /// <summary> /// Gets the composable part assemblies. /// </summary> /// <returns>IEnumerable{Assembly}.</returns> diff --git a/MediaBrowser.Common/Logging/Logger.cs b/MediaBrowser.Common/Logging/Logger.cs index 33d6b7f73..a6cb6d885 100644 --- a/MediaBrowser.Common/Logging/Logger.cs +++ b/MediaBrowser.Common/Logging/Logger.cs @@ -35,16 +35,6 @@ namespace MediaBrowser.Common.Logging } /// <summary> - /// Logs the error. - /// </summary> - /// <param name="message">The message.</param> - /// <param name="paramList">The param list.</param> - public static void LogError(string message, params object[] paramList) - { - LogEntry(message, LogSeverity.Error, null, paramList); - } - - /// <summary> /// Logs the exception. /// </summary> /// <param name="message">The message.</param> @@ -54,17 +44,6 @@ namespace MediaBrowser.Common.Logging { LogEntry(message, LogSeverity.Error, ex, paramList); } - - /// <summary> - /// Fatals the exception. - /// </summary> - /// <param name="message">The message.</param> - /// <param name="ex">The ex.</param> - /// <param name="paramList">The param list.</param> - public static void FatalException(string message, Exception ex, params object[] paramList) - { - LogEntry(message, LogSeverity.Fatal, ex, paramList); - } /// <summary> /// Logs the warning. diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index cef79fe56..8d2a68cb8 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -202,12 +202,14 @@ namespace MediaBrowser.Controller.Entities /// <returns>Dictionary{System.StringIComparer{BaseItem}}.</returns> protected virtual Dictionary<string, IComparer<BaseItem>> GetSortByOptions() { + var logger = LogManager.GetLogger("BaseItemComparer"); + return new Dictionary<string, IComparer<BaseItem>> { - {LocalizedStrings.Instance.GetString("NameDispPref"), new BaseItemComparer(SortOrder.Name)}, - {LocalizedStrings.Instance.GetString("DateDispPref"), new BaseItemComparer(SortOrder.Date)}, - {LocalizedStrings.Instance.GetString("RatingDispPref"), new BaseItemComparer(SortOrder.Rating)}, - {LocalizedStrings.Instance.GetString("RuntimeDispPref"), new BaseItemComparer(SortOrder.Runtime)}, - {LocalizedStrings.Instance.GetString("YearDispPref"), new BaseItemComparer(SortOrder.Year)} + {LocalizedStrings.Instance.GetString("NameDispPref"), new BaseItemComparer(SortOrder.Name, logger)}, + {LocalizedStrings.Instance.GetString("DateDispPref"), new BaseItemComparer(SortOrder.Date, logger)}, + {LocalizedStrings.Instance.GetString("RatingDispPref"), new BaseItemComparer(SortOrder.Rating, logger)}, + {LocalizedStrings.Instance.GetString("RuntimeDispPref"), new BaseItemComparer(SortOrder.Runtime, logger)}, + {LocalizedStrings.Instance.GetString("YearDispPref"), new BaseItemComparer(SortOrder.Year, logger)} }; } @@ -221,7 +223,7 @@ namespace MediaBrowser.Controller.Entities { IComparer<BaseItem> sorting; SortByOptions.TryGetValue(name ?? "", out sorting); - return sorting ?? new BaseItemComparer(SortOrder.Name); + return sorting ?? new BaseItemComparer(SortOrder.Name, LogManager.GetLogger("BaseItemComparer")); } /// <summary> diff --git a/MediaBrowser.Controller/Kernel.cs b/MediaBrowser.Controller/Kernel.cs index f8f48d8de..b4c553c66 100644 --- a/MediaBrowser.Controller/Kernel.cs +++ b/MediaBrowser.Controller/Kernel.cs @@ -16,10 +16,12 @@ using MediaBrowser.Controller.Updates; using MediaBrowser.Controller.Weather; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.IO; +using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.System; using System; using System.Collections.Generic; using System.ComponentModel.Composition; +using System.ComponentModel.Composition.Hosting; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -305,13 +307,47 @@ namespace MediaBrowser.Controller private IZipClient ZipClient { get; set; } /// <summary> + /// Gets or sets the bluray examiner. + /// </summary> + /// <value>The bluray examiner.</value> + private IBlurayExaminer BlurayExaminer { get; set; } + + /// <summary> /// Creates a kernel based on a Data path, which is akin to our current programdata path /// </summary> - public Kernel(IIsoManager isoManager, IZipClient zipClient) + public Kernel(IIsoManager isoManager, IZipClient zipClient, IBlurayExaminer blurayExaminer) : base(isoManager) { + if (isoManager == null) + { + throw new ArgumentNullException("isoManager"); + } + + if (zipClient == null) + { + throw new ArgumentNullException("zipClient"); + } + + if (blurayExaminer == null) + { + throw new ArgumentNullException("blurayExaminer"); + } + Instance = this; ZipClient = zipClient; + BlurayExaminer = blurayExaminer; + } + + /// <summary> + /// Composes the exported values. + /// </summary> + /// <param name="container">The container.</param> + protected override void ComposeExportedValues(CompositionContainer container) + { + base.ComposeExportedValues(container); + + container.ComposeExportedValue("kernel", this); + container.ComposeExportedValue("blurayExaminer", BlurayExaminer); } /// <summary> diff --git a/MediaBrowser.Controller/Library/DtoBuilder.cs b/MediaBrowser.Controller/Library/DtoBuilder.cs index b16671e9e..3fa438175 100644 --- a/MediaBrowser.Controller/Library/DtoBuilder.cs +++ b/MediaBrowser.Controller/Library/DtoBuilder.cs @@ -6,6 +6,7 @@ using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.DTO; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; using System.IO; @@ -24,6 +25,8 @@ namespace MediaBrowser.Controller.Library /// </summary> const string IndexFolderDelimeter = "-index-"; + private static ILogger Logger = LogManager.GetLogger("DtoBuilder"); + /// <summary> /// Gets the dto base item. /// </summary> @@ -55,7 +58,7 @@ namespace MediaBrowser.Controller.Library catch (Exception ex) { // Have to use a catch-all unfortunately because some .net image methods throw plain Exceptions - Logger.LogException("Error generating PrimaryImageAspectRatio for {0}", ex, item.Name); + Logger.ErrorException("Error generating PrimaryImageAspectRatio for {0}", ex, item.Name); } } @@ -116,7 +119,7 @@ namespace MediaBrowser.Controller.Library catch (Exception ex) { // Have to use a catch-all unfortunately because some .net image methods throw plain Exceptions - Logger.LogException("Error generating PrimaryImageAspectRatio for {0}", ex, item.Name); + Logger.ErrorException("Error generating PrimaryImageAspectRatio for {0}", ex, item.Name); } } @@ -211,7 +214,7 @@ namespace MediaBrowser.Controller.Library } catch (FileNotFoundException) { - Logger.LogError("Image file does not exist: {0}", path); + Logger.Error("Image file does not exist: {0}", path); return; } @@ -572,7 +575,7 @@ namespace MediaBrowser.Controller.Library } catch (IOException ex) { - Logger.LogException("Error getting person {0}", ex, c.Name); + Logger.ErrorException("Error getting person {0}", ex, c.Name); return null; } }) diff --git a/MediaBrowser.Controller/Localization/Ratings.cs b/MediaBrowser.Controller/Localization/Ratings.cs index 946e25f53..2f7188a9b 100644 --- a/MediaBrowser.Controller/Localization/Ratings.cs +++ b/MediaBrowser.Controller/Localization/Ratings.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using MediaBrowser.Common.Logging; namespace MediaBrowser.Controller.Localization { @@ -39,7 +40,7 @@ namespace MediaBrowser.Controller.Localization public static Dictionary<string, int> Initialize(bool blockUnrated) { //build our ratings dictionary from the combined local one and us one - ratingsDef = new RatingsDefinition(Path.Combine(Kernel.Instance.ApplicationPaths.LocalizationPath, "Ratings-" + Kernel.Instance.Configuration.MetadataCountryCode+".txt")); + ratingsDef = new RatingsDefinition(Path.Combine(Kernel.Instance.ApplicationPaths.LocalizationPath, "Ratings-" + Kernel.Instance.Configuration.MetadataCountryCode + ".txt"), LogManager.GetLogger("RatingsDefinition")); //global value of None var dict = new Dictionary<string, int> {{"None", -1}}; foreach (var pair in ratingsDef.RatingsDict) diff --git a/MediaBrowser.Controller/Localization/RatingsDefinition.cs b/MediaBrowser.Controller/Localization/RatingsDefinition.cs index 65bd3bcbb..e0753da2e 100644 --- a/MediaBrowser.Controller/Localization/RatingsDefinition.cs +++ b/MediaBrowser.Controller/Localization/RatingsDefinition.cs @@ -1,7 +1,7 @@ -using System; +using MediaBrowser.Model.Logging; +using System; using System.Collections.Generic; using System.IO; -using MediaBrowser.Common.Logging; namespace MediaBrowser.Controller.Localization { @@ -11,12 +11,21 @@ namespace MediaBrowser.Controller.Localization public class RatingsDefinition { /// <summary> + /// Gets or sets the logger. + /// </summary> + /// <value>The logger.</value> + private ILogger Logger { get; set; } + + /// <summary> /// Initializes a new instance of the <see cref="RatingsDefinition" /> class. /// </summary> /// <param name="file">The file.</param> - public RatingsDefinition(string file) + /// <param name="logger">The logger.</param> + public RatingsDefinition(string file, ILogger logger) { - Logger.LogInfo("Loading Certification Ratings from file " + file); + Logger = logger; + + Logger.Info("Loading Certification Ratings from file " + file); this.file = file; if (!Load()) { @@ -99,7 +108,7 @@ namespace MediaBrowser.Controller.Localization } else { - Logger.LogError("Invalid line in ratings file " + file + "(" + line + ")"); + Logger.Error("Invalid line in ratings file " + file + "(" + line + ")"); } } } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index da2bc23e8..58e1b3fb0 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -119,7 +119,6 @@ <Compile Include="Localization\Ratings.cs" /> <Compile Include="Localization\RatingsDefinition.cs" /> <Compile Include="Localization\USRatingsDictionary.cs" /> - <Compile Include="MediaInfo\BDInfoResult.cs" /> <Compile Include="MediaInfo\FFMpegManager.cs" /> <Compile Include="MediaInfo\FFProbeResult.cs" /> <Compile Include="Persistence\IDisplayPreferencesRepository.cs" /> @@ -136,7 +135,6 @@ <Compile Include="Providers\ImagesByNameProvider.cs" /> <Compile Include="Providers\MediaInfo\BaseFFMpegImageProvider.cs" /> <Compile Include="Providers\MediaInfo\BaseFFMpegProvider.cs" /> - <Compile Include="Providers\MediaInfo\BDInfoProvider.cs" /> <Compile Include="Providers\MediaInfo\FFMpegAudioImageProvider.cs" /> <Compile Include="Providers\MediaInfo\BaseFFProbeProvider.cs" /> <Compile Include="Providers\BaseProviderInfo.cs" /> @@ -203,10 +201,6 @@ <Compile Include="Providers\BaseItemXmlParser.cs" /> </ItemGroup> <ItemGroup> - <ProjectReference Include="..\BDInfo\BDInfo.csproj"> - <Project>{07b509c0-0c28-4f3f-8963-5263281f7e3d}</Project> - <Name>BDInfo</Name> - </ProjectReference> <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj"> <Project>{9142eefa-7570-41e1-bfcc-468bb571af2f}</Project> <Name>MediaBrowser.Common</Name> diff --git a/MediaBrowser.Controller/Providers/MediaInfo/BDInfoProvider.cs b/MediaBrowser.Controller/Providers/MediaInfo/BDInfoProvider.cs deleted file mode 100644 index 6214cb0da..000000000 --- a/MediaBrowser.Controller/Providers/MediaInfo/BDInfoProvider.cs +++ /dev/null @@ -1,265 +0,0 @@ -using BDInfo; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.MediaInfo; -using MediaBrowser.Model.Entities; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; - -namespace MediaBrowser.Controller.Providers.MediaInfo -{ - /// <summary> - /// Extracts dvd information using VgtMpeg - /// </summary> - internal static class BDInfoProvider - { - internal static void FetchBdInfo(BaseItem item, string inputPath, FileSystemRepository bdInfoCache, CancellationToken cancellationToken) - { - var video = (Video)item; - - // Get the path to the cache file - var cacheName = item.Id + "_" + item.DateModified.Ticks; - - var cacheFile = bdInfoCache.GetResourcePath(cacheName, ".pb"); - - BDInfoResult result; - - try - { - result = Kernel.Instance.ProtobufSerializer.DeserializeFromFile<BDInfoResult>(cacheFile); - } - catch (FileNotFoundException) - { - result = GetBDInfo(inputPath); - - Kernel.Instance.ProtobufSerializer.SerializeToFile(result, cacheFile); - } - - cancellationToken.ThrowIfCancellationRequested(); - - int? currentHeight = null; - int? currentWidth = null; - int? currentBitRate = null; - - var videoStream = video.MediaStreams.FirstOrDefault(s => s.Type == MediaStreamType.Video); - - // Grab the values that ffprobe recorded - if (videoStream != null) - { - currentBitRate = videoStream.BitRate; - currentWidth = videoStream.Width; - currentHeight = videoStream.Height; - } - - // Fill video properties from the BDInfo result - Fetch(video, inputPath, result); - - videoStream = video.MediaStreams.FirstOrDefault(s => s.Type == MediaStreamType.Video); - - // Use the ffprobe values if these are empty - if (videoStream != null) - { - videoStream.BitRate = IsEmpty(videoStream.BitRate) ? currentBitRate : videoStream.BitRate; - videoStream.Width = IsEmpty(videoStream.Width) ? currentWidth : videoStream.Width; - videoStream.Height = IsEmpty(videoStream.Height) ? currentHeight : videoStream.Height; - } - } - - /// <summary> - /// Determines whether the specified num is empty. - /// </summary> - /// <param name="num">The num.</param> - /// <returns><c>true</c> if the specified num is empty; otherwise, <c>false</c>.</returns> - private static bool IsEmpty(int? num) - { - return !num.HasValue || num.Value == 0; - } - - /// <summary> - /// Fills video properties from the VideoStream of the largest playlist - /// </summary> - /// <param name="video">The video.</param> - /// <param name="inputPath">The input path.</param> - /// <param name="stream">The stream.</param> - private static void Fetch(Video video, string inputPath, BDInfoResult stream) - { - // Check all input for null/empty/zero - - video.MediaStreams = stream.MediaStreams; - - if (stream.RunTimeTicks.HasValue && stream.RunTimeTicks.Value > 0) - { - video.RunTimeTicks = stream.RunTimeTicks; - } - - video.PlayableStreamFileNames = stream.Files.ToList(); - - if (stream.Chapters != null) - { - video.Chapters = stream.Chapters.Select(c => new ChapterInfo - { - StartPositionTicks = TimeSpan.FromSeconds(c).Ticks - - }).ToList(); - } - } - - /// <summary> - /// Gets information about the longest playlist on a bdrom - /// </summary> - /// <param name="path">The path.</param> - /// <returns>VideoStream.</returns> - private static BDInfoResult GetBDInfo(string path) - { - var bdrom = new BDROM(path); - - bdrom.Scan(); - - // Get the longest playlist - var playlist = bdrom.PlaylistFiles.Values.OrderByDescending(p => p.TotalLength).FirstOrDefault(p => p.IsValid); - - var outputStream = new BDInfoResult - { - MediaStreams = new List<MediaStream>() - }; - - if (playlist == null) - { - return outputStream; - } - - outputStream.Chapters = playlist.Chapters; - - outputStream.RunTimeTicks = TimeSpan.FromSeconds(playlist.TotalLength).Ticks; - - var mediaStreams = new List<MediaStream> {}; - - foreach (var stream in playlist.SortedStreams) - { - var videoStream = stream as TSVideoStream; - - if (videoStream != null) - { - AddVideoStream(mediaStreams, videoStream); - continue; - } - - var audioStream = stream as TSAudioStream; - - if (audioStream != null) - { - AddAudioStream(mediaStreams, audioStream); - continue; - } - - var textStream = stream as TSTextStream; - - if (textStream != null) - { - AddSubtitleStream(mediaStreams, textStream); - continue; - } - - var graphicsStream = stream as TSGraphicsStream; - - if (graphicsStream != null) - { - AddSubtitleStream(mediaStreams, graphicsStream); - } - } - - outputStream.MediaStreams = mediaStreams; - - if (playlist.StreamClips != null && playlist.StreamClips.Any()) - { - // Get the files in the playlist - outputStream.Files = playlist.StreamClips.Select(i => i.StreamFile.Name).ToList(); - } - - return outputStream; - } - - /// <summary> - /// Adds the video stream. - /// </summary> - /// <param name="streams">The streams.</param> - /// <param name="videoStream">The video stream.</param> - private static void AddVideoStream(List<MediaStream> streams, TSVideoStream videoStream) - { - var mediaStream = new MediaStream - { - BitRate = Convert.ToInt32(videoStream.BitRate), - Width = videoStream.Width, - Height = videoStream.Height, - Codec = videoStream.CodecShortName, - ScanType = videoStream.IsInterlaced ? "interlaced" : "progressive", - Type = MediaStreamType.Video, - Index = streams.Count - }; - - if (videoStream.FrameRateDenominator > 0) - { - float frameRateEnumerator = videoStream.FrameRateEnumerator; - float frameRateDenominator = videoStream.FrameRateDenominator; - - mediaStream.AverageFrameRate = mediaStream.RealFrameRate = frameRateEnumerator / frameRateDenominator; - } - - streams.Add(mediaStream); - } - - /// <summary> - /// Adds the audio stream. - /// </summary> - /// <param name="streams">The streams.</param> - /// <param name="audioStream">The audio stream.</param> - private static void AddAudioStream(List<MediaStream> streams, TSAudioStream audioStream) - { - streams.Add(new MediaStream - { - BitRate = Convert.ToInt32(audioStream.BitRate), - Codec = audioStream.CodecShortName, - Language = audioStream.LanguageCode, - Channels = audioStream.ChannelCount, - SampleRate = audioStream.SampleRate, - Type = MediaStreamType.Audio, - Index = streams.Count - }); - } - - /// <summary> - /// Adds the subtitle stream. - /// </summary> - /// <param name="streams">The streams.</param> - /// <param name="textStream">The text stream.</param> - private static void AddSubtitleStream(List<MediaStream> streams, TSTextStream textStream) - { - streams.Add(new MediaStream - { - Language = textStream.LanguageCode, - Codec = textStream.CodecShortName, - Type = MediaStreamType.Subtitle, - Index = streams.Count - }); - } - - /// <summary> - /// Adds the subtitle stream. - /// </summary> - /// <param name="streams">The streams.</param> - /// <param name="textStream">The text stream.</param> - private static void AddSubtitleStream(List<MediaStream> streams, TSGraphicsStream textStream) - { - streams.Add(new MediaStream - { - Language = textStream.LanguageCode, - Codec = textStream.CodecShortName, - Type = MediaStreamType.Subtitle, - Index = streams.Count - }); - } - } -} diff --git a/MediaBrowser.Controller/Providers/MediaInfo/FFProbeVideoInfoProvider.cs b/MediaBrowser.Controller/Providers/MediaInfo/FFProbeVideoInfoProvider.cs index 5092429e8..2df495b23 100644 --- a/MediaBrowser.Controller/Providers/MediaInfo/FFProbeVideoInfoProvider.cs +++ b/MediaBrowser.Controller/Providers/MediaInfo/FFProbeVideoInfoProvider.cs @@ -3,6 +3,7 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.MediaInfo; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.MediaInfo; using System; using System.Collections.Generic; using System.ComponentModel.Composition; @@ -26,11 +27,27 @@ namespace MediaBrowser.Controller.Providers.MediaInfo private FileSystemRepository BdInfoCache { get; set; } /// <summary> + /// Gets or sets the bluray examiner. + /// </summary> + /// <value>The bluray examiner.</value> + private IBlurayExaminer BlurayExaminer { get; set; } + + /// <summary> /// Initializes a new instance of the <see cref="FFProbeVideoInfoProvider" /> class. /// </summary> - public FFProbeVideoInfoProvider() + /// <param name="blurayExaminer">The bluray examiner.</param> + /// <exception cref="System.ArgumentNullException">blurayExaminer</exception> + [ImportingConstructor] + public FFProbeVideoInfoProvider([Import("blurayExaminer")] IBlurayExaminer blurayExaminer) : base() { + if (blurayExaminer == null) + { + throw new ArgumentNullException("blurayExaminer"); + } + + BlurayExaminer = blurayExaminer; + BdInfoCache = new FileSystemRepository(Path.Combine(Kernel.Instance.ApplicationPaths.CachePath, "bdinfo")); } @@ -183,7 +200,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo if (video.VideoType == VideoType.BluRay || (video.IsoType.HasValue && video.IsoType.Value == IsoType.BluRay)) { var inputPath = isoMount != null ? isoMount.MountedPath : video.Path; - BDInfoProvider.FetchBdInfo(video, inputPath, BdInfoCache, cancellationToken); + FetchBdInfo(video, inputPath, BdInfoCache, cancellationToken); } AddExternalSubtitles(video); @@ -239,7 +256,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo /// <summary> /// The dummy chapter duration /// </summary> - private static readonly long DummyChapterDuration = TimeSpan.FromMinutes(10).Ticks; + private readonly long DummyChapterDuration = TimeSpan.FromMinutes(10).Ticks; /// <summary> /// Adds the dummy chapters. @@ -275,6 +292,114 @@ namespace MediaBrowser.Controller.Providers.MediaInfo } /// <summary> + /// Fetches the bd info. + /// </summary> + /// <param name="item">The item.</param> + /// <param name="inputPath">The input path.</param> + /// <param name="bdInfoCache">The bd info cache.</param> + /// <param name="cancellationToken">The cancellation token.</param> + private void FetchBdInfo(BaseItem item, string inputPath, FileSystemRepository bdInfoCache, CancellationToken cancellationToken) + { + var video = (Video)item; + + // Get the path to the cache file + var cacheName = item.Id + "_" + item.DateModified.Ticks; + + var cacheFile = bdInfoCache.GetResourcePath(cacheName, ".pb"); + + BlurayDiscInfo result; + + try + { + result = Kernel.Instance.ProtobufSerializer.DeserializeFromFile<BlurayDiscInfo>(cacheFile); + } + catch (FileNotFoundException) + { + result = GetBDInfo(inputPath); + + Kernel.Instance.ProtobufSerializer.SerializeToFile(result, cacheFile); + } + + cancellationToken.ThrowIfCancellationRequested(); + + int? currentHeight = null; + int? currentWidth = null; + int? currentBitRate = null; + + var videoStream = video.MediaStreams.FirstOrDefault(s => s.Type == MediaStreamType.Video); + + // Grab the values that ffprobe recorded + if (videoStream != null) + { + currentBitRate = videoStream.BitRate; + currentWidth = videoStream.Width; + currentHeight = videoStream.Height; + } + + // Fill video properties from the BDInfo result + Fetch(video, inputPath, result); + + videoStream = video.MediaStreams.FirstOrDefault(s => s.Type == MediaStreamType.Video); + + // Use the ffprobe values if these are empty + if (videoStream != null) + { + videoStream.BitRate = IsEmpty(videoStream.BitRate) ? currentBitRate : videoStream.BitRate; + videoStream.Width = IsEmpty(videoStream.Width) ? currentWidth : videoStream.Width; + videoStream.Height = IsEmpty(videoStream.Height) ? currentHeight : videoStream.Height; + } + } + + /// <summary> + /// Determines whether the specified num is empty. + /// </summary> + /// <param name="num">The num.</param> + /// <returns><c>true</c> if the specified num is empty; otherwise, <c>false</c>.</returns> + private bool IsEmpty(int? num) + { + return !num.HasValue || num.Value == 0; + } + + /// <summary> + /// Fills video properties from the VideoStream of the largest playlist + /// </summary> + /// <param name="video">The video.</param> + /// <param name="inputPath">The input path.</param> + /// <param name="stream">The stream.</param> + private void Fetch(Video video, string inputPath, BlurayDiscInfo stream) + { + // Check all input for null/empty/zero + + video.MediaStreams = stream.MediaStreams; + + if (stream.RunTimeTicks.HasValue && stream.RunTimeTicks.Value > 0) + { + video.RunTimeTicks = stream.RunTimeTicks; + } + + video.PlayableStreamFileNames = stream.Files.ToList(); + + if (stream.Chapters != null) + { + video.Chapters = stream.Chapters.Select(c => new ChapterInfo + { + StartPositionTicks = TimeSpan.FromSeconds(c).Ticks + + }).ToList(); + } + } + + /// <summary> + /// Gets information about the longest playlist on a bdrom + /// </summary> + /// <param name="path">The path.</param> + /// <returns>VideoStream.</returns> + private BlurayDiscInfo GetBDInfo(string path) + { + return BlurayExaminer.GetDiscInfo(path); + } + + /// <summary> /// Releases unmanaged and - optionally - managed resources. /// </summary> /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> diff --git a/MediaBrowser.Controller/Sorting/BaseItemComparer.cs b/MediaBrowser.Controller/Sorting/BaseItemComparer.cs index 6e49f396f..94c16775d 100644 --- a/MediaBrowser.Controller/Sorting/BaseItemComparer.cs +++ b/MediaBrowser.Controller/Sorting/BaseItemComparer.cs @@ -1,5 +1,5 @@ -using MediaBrowser.Common.Logging; -using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Logging; using System; using System.Collections.Generic; @@ -22,11 +22,19 @@ namespace MediaBrowser.Controller.Sorting { private readonly StringComparison _compareCulture = StringComparison.CurrentCultureIgnoreCase; /// <summary> + /// Gets or sets the logger. + /// </summary> + /// <value>The logger.</value> + private ILogger Logger { get; set; } + + /// <summary> /// Initializes a new instance of the <see cref="BaseItemComparer" /> class. /// </summary> /// <param name="order">The order.</param> - public BaseItemComparer(SortOrder order) { + /// <param name="logger">The logger.</param> + public BaseItemComparer(SortOrder order, ILogger logger) { _order = order; + Logger = logger; } /// <summary> @@ -34,18 +42,24 @@ namespace MediaBrowser.Controller.Sorting { /// </summary> /// <param name="order">The order.</param> /// <param name="compare">The compare.</param> - public BaseItemComparer(SortOrder order, StringComparison compare) { + /// <param name="logger">The logger.</param> + public BaseItemComparer(SortOrder order, StringComparison compare, ILogger logger) + { _order = order; _compareCulture = compare; + Logger = logger; } /// <summary> /// Initializes a new instance of the <see cref="BaseItemComparer" /> class. /// </summary> /// <param name="property">The property.</param> - public BaseItemComparer(string property) { + /// <param name="logger">The logger.</param> + public BaseItemComparer(string property, ILogger logger) + { _order = SortOrder.Custom; _propertyName = property; + Logger = logger; } /// <summary> @@ -53,10 +67,13 @@ namespace MediaBrowser.Controller.Sorting { /// </summary> /// <param name="property">The property.</param> /// <param name="compare">The compare.</param> - public BaseItemComparer(string property, StringComparison compare) { + /// <param name="logger">The logger.</param> + public BaseItemComparer(string property, StringComparison compare, ILogger logger) + { _order = SortOrder.Custom; _propertyName = property; _compareCulture = compare; + Logger = logger; } #region IComparer<BaseItem> Members @@ -102,7 +119,7 @@ namespace MediaBrowser.Controller.Sorting { case SortOrder.Custom: - Logger.LogDebugInfo("Sorting on custom field " + _propertyName); + Logger.Debug("Sorting on custom field " + _propertyName); var yProp = y.GetType().GetProperty(_propertyName); var xProp = x.GetType().GetProperty(_propertyName); if (yProp == null || xProp == null) break; @@ -143,7 +160,7 @@ namespace MediaBrowser.Controller.Sorting { /// <param name="s2">The s2.</param> /// <param name="compareCulture">The compare culture.</param> /// <returns>System.Int32.</returns> - public static int AlphaNumericCompare(string s1, string s2, StringComparison compareCulture) { + private int AlphaNumericCompare(string s1, string s2, StringComparison compareCulture) { // http://dotnetperls.com/Content/Alphanumeric-Sorting.aspx int len1 = s1.Length; @@ -213,7 +230,7 @@ namespace MediaBrowser.Controller.Sorting { if (!isValid) { - Logger.LogError("Error comparing numeric strings: " + str1 + "/" + str2); + Logger.Error("Error comparing numeric strings: " + str1 + "/" + str2); result = String.Compare(str1, str2, compareCulture); } diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index dd11a131a..a9c3fcfec 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -45,6 +45,7 @@ <Compile Include="Entities\BaseItemInfo.cs" /> <Compile Include="Connectivity\ClientConnectionInfo.cs" /> <Compile Include="Connectivity\ClientType.cs" /> + <Compile Include="MediaInfo\BlurayDiscInfo.cs" /> <Compile Include="Entities\ChapterInfo.cs" /> <Compile Include="Entities\LocationType.cs" /> <Compile Include="Entities\MBRegistrationRecord.cs" /> @@ -67,6 +68,7 @@ <Compile Include="IO\IZipClient.cs" /> <Compile Include="Logging\ILogger.cs" /> <Compile Include="Logging\LogSeverity.cs" /> + <Compile Include="MediaInfo\IBlurayExaminer.cs" /> <Compile Include="Net\HttpException.cs" /> <Compile Include="Updates\InstallationInfo.cs" /> <Compile Include="Updates\PackageType.cs" /> diff --git a/MediaBrowser.Controller/MediaInfo/BDInfoResult.cs b/MediaBrowser.Model/MediaInfo/BlurayDiscInfo.cs index 08d1ce8a0..1a05cfe09 100644 --- a/MediaBrowser.Controller/MediaInfo/BDInfoResult.cs +++ b/MediaBrowser.Model/MediaInfo/BlurayDiscInfo.cs @@ -2,13 +2,13 @@ using ProtoBuf; using System.Collections.Generic; -namespace MediaBrowser.Controller.MediaInfo +namespace MediaBrowser.Model.MediaInfo { /// <summary> /// Represents the result of BDInfo output /// </summary> [ProtoContract] - public class BDInfoResult + public class BlurayDiscInfo { /// <summary> /// Gets or sets the media streams. diff --git a/MediaBrowser.Model/MediaInfo/IBlurayExaminer.cs b/MediaBrowser.Model/MediaInfo/IBlurayExaminer.cs new file mode 100644 index 000000000..78d5b197f --- /dev/null +++ b/MediaBrowser.Model/MediaInfo/IBlurayExaminer.cs @@ -0,0 +1,16 @@ + +namespace MediaBrowser.Model.MediaInfo +{ + /// <summary> + /// Interface IBlurayExaminer + /// </summary> + public interface IBlurayExaminer + { + /// <summary> + /// Gets the disc info. + /// </summary> + /// <param name="path">The path.</param> + /// <returns>BlurayDiscInfo.</returns> + BlurayDiscInfo GetDiscInfo(string path); + } +} diff --git a/MediaBrowser.ServerApplication/App.xaml.cs b/MediaBrowser.ServerApplication/App.xaml.cs index b06c8f04e..f52a1cbf0 100644 --- a/MediaBrowser.ServerApplication/App.xaml.cs +++ b/MediaBrowser.ServerApplication/App.xaml.cs @@ -170,7 +170,7 @@ namespace MediaBrowser.ServerApplication /// <returns>IKernel.</returns> protected override IKernel InstantiateKernel() { - return new Kernel(new PismoIsoManager(LogManager.GetLogger("PismoIsoManager")), new DotNetZipClient()); + return new Kernel(new PismoIsoManager(LogManager.GetLogger("PismoIsoManager")), new DotNetZipClient(), new BdInfoExaminer()); } /// <summary> diff --git a/MediaBrowser.ServerApplication/Implementations/BdInfoExaminer.cs b/MediaBrowser.ServerApplication/Implementations/BdInfoExaminer.cs new file mode 100644 index 000000000..dbde630be --- /dev/null +++ b/MediaBrowser.ServerApplication/Implementations/BdInfoExaminer.cs @@ -0,0 +1,170 @@ +using BDInfo; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.MediaInfo; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace MediaBrowser.ServerApplication.Implementations +{ + /// <summary> + /// Class BdInfoExaminer + /// </summary> + public class BdInfoExaminer : IBlurayExaminer + { + /// <summary> + /// Gets the disc info. + /// </summary> + /// <param name="path">The path.</param> + /// <returns>BlurayDiscInfo.</returns> + public BlurayDiscInfo GetDiscInfo(string path) + { + var bdrom = new BDROM(path); + + bdrom.Scan(); + + // Get the longest playlist + var playlist = bdrom.PlaylistFiles.Values.OrderByDescending(p => p.TotalLength).FirstOrDefault(p => p.IsValid); + + var outputStream = new BlurayDiscInfo + { + MediaStreams = new List<MediaStream>() + }; + + if (playlist == null) + { + return outputStream; + } + + outputStream.Chapters = playlist.Chapters; + + outputStream.RunTimeTicks = TimeSpan.FromSeconds(playlist.TotalLength).Ticks; + + var mediaStreams = new List<MediaStream> { }; + + foreach (var stream in playlist.SortedStreams) + { + var videoStream = stream as TSVideoStream; + + if (videoStream != null) + { + AddVideoStream(mediaStreams, videoStream); + continue; + } + + var audioStream = stream as TSAudioStream; + + if (audioStream != null) + { + AddAudioStream(mediaStreams, audioStream); + continue; + } + + var textStream = stream as TSTextStream; + + if (textStream != null) + { + AddSubtitleStream(mediaStreams, textStream); + continue; + } + + var graphicsStream = stream as TSGraphicsStream; + + if (graphicsStream != null) + { + AddSubtitleStream(mediaStreams, graphicsStream); + } + } + + outputStream.MediaStreams = mediaStreams; + + if (playlist.StreamClips != null && playlist.StreamClips.Any()) + { + // Get the files in the playlist + outputStream.Files = playlist.StreamClips.Select(i => i.StreamFile.Name).ToList(); + } + + return outputStream; + } + + /// <summary> + /// Adds the video stream. + /// </summary> + /// <param name="streams">The streams.</param> + /// <param name="videoStream">The video stream.</param> + private void AddVideoStream(List<MediaStream> streams, TSVideoStream videoStream) + { + var mediaStream = new MediaStream + { + BitRate = Convert.ToInt32(videoStream.BitRate), + Width = videoStream.Width, + Height = videoStream.Height, + Codec = videoStream.CodecShortName, + ScanType = videoStream.IsInterlaced ? "interlaced" : "progressive", + Type = MediaStreamType.Video, + Index = streams.Count + }; + + if (videoStream.FrameRateDenominator > 0) + { + float frameRateEnumerator = videoStream.FrameRateEnumerator; + float frameRateDenominator = videoStream.FrameRateDenominator; + + mediaStream.AverageFrameRate = mediaStream.RealFrameRate = frameRateEnumerator / frameRateDenominator; + } + + streams.Add(mediaStream); + } + + /// <summary> + /// Adds the audio stream. + /// </summary> + /// <param name="streams">The streams.</param> + /// <param name="audioStream">The audio stream.</param> + private void AddAudioStream(List<MediaStream> streams, TSAudioStream audioStream) + { + streams.Add(new MediaStream + { + BitRate = Convert.ToInt32(audioStream.BitRate), + Codec = audioStream.CodecShortName, + Language = audioStream.LanguageCode, + Channels = audioStream.ChannelCount, + SampleRate = audioStream.SampleRate, + Type = MediaStreamType.Audio, + Index = streams.Count + }); + } + + /// <summary> + /// Adds the subtitle stream. + /// </summary> + /// <param name="streams">The streams.</param> + /// <param name="textStream">The text stream.</param> + private void AddSubtitleStream(List<MediaStream> streams, TSTextStream textStream) + { + streams.Add(new MediaStream + { + Language = textStream.LanguageCode, + Codec = textStream.CodecShortName, + Type = MediaStreamType.Subtitle, + Index = streams.Count + }); + } + + /// <summary> + /// Adds the subtitle stream. + /// </summary> + /// <param name="streams">The streams.</param> + /// <param name="textStream">The text stream.</param> + private void AddSubtitleStream(List<MediaStream> streams, TSGraphicsStream textStream) + { + streams.Add(new MediaStream + { + Language = textStream.LanguageCode, + Codec = textStream.CodecShortName, + Type = MediaStreamType.Subtitle, + Index = streams.Count + }); + } + } +} diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index cfd37904e..41e90a38f 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -179,6 +179,7 @@ <Compile Include="Controls\MultiItemUpdateNotification.xaml.cs"> <DependentUpon>MultiItemUpdateNotification.xaml</DependentUpon> </Compile> + <Compile Include="Implementations\BdInfoExaminer.cs" /> <Compile Include="Implementations\DotNetZipClient.cs" /> <Compile Include="LibraryExplorer.xaml.cs"> <DependentUpon>LibraryExplorer.xaml</DependentUpon> @@ -221,6 +222,10 @@ </None> </ItemGroup> <ItemGroup> + <ProjectReference Include="..\BDInfo\BDInfo.csproj"> + <Project>{07b509c0-0c28-4f3f-8963-5263281f7e3d}</Project> + <Name>BDInfo</Name> + </ProjectReference> <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj"> <Project>{9142eefa-7570-41e1-bfcc-468bb571af2f}</Project> <Name>MediaBrowser.Common</Name> diff --git a/MediaBrowser.UI.sln b/MediaBrowser.UI.sln index 0bb86a09f..06d1c5f8b 100644 --- a/MediaBrowser.UI.sln +++ b/MediaBrowser.UI.sln @@ -19,8 +19,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Plugins.Tmt5", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.UI.Uninstall", "MediaBrowser.UI.Uninstall\MediaBrowser.UI.Uninstall.csproj", "{E4BE0659-4084-407B-B8A8-67802331CC9E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BDInfo", "BDInfo\BDInfo.csproj", "{07B509C0-0C28-4F3F-8963-5263281F7E3D}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.IsoMounter", "MediaBrowser.IsoMounter\MediaBrowser.IsoMounter.csproj", "{5356AE30-6A6E-4A64-81E3-F76C50595E64}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.UI.Controls", "MediaBrowser.UI.Controls\MediaBrowser.UI.Controls.csproj", "{1ADFE460-FD95-46FA-8871-CCCB4B62E2E8}" @@ -137,16 +135,6 @@ Global {E4BE0659-4084-407B-B8A8-67802331CC9E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU {E4BE0659-4084-407B-B8A8-67802331CC9E}.Release|Mixed Platforms.Build.0 = Release|Any CPU {E4BE0659-4084-407B-B8A8-67802331CC9E}.Release|x86.ActiveCfg = Release|Any CPU - {07B509C0-0C28-4F3F-8963-5263281F7E3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {07B509C0-0C28-4F3F-8963-5263281F7E3D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {07B509C0-0C28-4F3F-8963-5263281F7E3D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {07B509C0-0C28-4F3F-8963-5263281F7E3D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {07B509C0-0C28-4F3F-8963-5263281F7E3D}.Debug|x86.ActiveCfg = Debug|Any CPU - {07B509C0-0C28-4F3F-8963-5263281F7E3D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {07B509C0-0C28-4F3F-8963-5263281F7E3D}.Release|Any CPU.Build.0 = Release|Any CPU - {07B509C0-0C28-4F3F-8963-5263281F7E3D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {07B509C0-0C28-4F3F-8963-5263281F7E3D}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {07B509C0-0C28-4F3F-8963-5263281F7E3D}.Release|x86.ActiveCfg = Release|Any CPU {5356AE30-6A6E-4A64-81E3-F76C50595E64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5356AE30-6A6E-4A64-81E3-F76C50595E64}.Debug|Any CPU.Build.0 = Debug|Any CPU {5356AE30-6A6E-4A64-81E3-F76C50595E64}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 |
