Forráskód Böngészése

isolated bdinfo dependancy

LukePulverenti 12 éve
szülő
commit
ee9d481662

+ 10 - 2
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);
 
@@ -493,6 +492,15 @@ namespace MediaBrowser.Common.Kernel
             CompositionContainer.Catalog.Dispose();
         }
 
+        /// <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>

+ 0 - 21
MediaBrowser.Common/Logging/Logger.cs

@@ -34,16 +34,6 @@ namespace MediaBrowser.Common.Logging
             LogEntry(message, LogSeverity.Debug, null, paramList);
         }
         
-        /// <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>
@@ -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.

+ 8 - 6
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>

+ 37 - 1
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;
@@ -304,14 +306,48 @@ namespace MediaBrowser.Controller
         /// <value>The zip client.</value>
         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>

+ 7 - 4
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;
                         }
                     })

+ 2 - 1
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)

+ 14 - 5
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
 {
@@ -10,13 +10,22 @@ namespace MediaBrowser.Controller.Localization
     /// </summary>
     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 + ")");
                             }
                         }
                     }

+ 0 - 6
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>

+ 0 - 265
MediaBrowser.Controller/Providers/MediaInfo/BDInfoProvider.cs

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

+ 128 - 3
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;
@@ -25,12 +26,28 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
         /// <value>The bd info cache.</value>
         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.
@@ -274,6 +291,114 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
             video.Chapters = chapters;
         }
 
+        /// <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>

+ 26 - 9
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;
 
@@ -21,12 +21,20 @@ namespace MediaBrowser.Controller.Sorting {
         /// </summary>
         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);
                     }
                     

+ 2 - 0
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" />

+ 2 - 2
MediaBrowser.Controller/MediaInfo/BDInfoResult.cs → 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.

+ 16 - 0
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);
+    }
+}

+ 1 - 1
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>

+ 170 - 0
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
+                });
+        }
+    }
+}

+ 5 - 0
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>

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