From defd8ed253a1e47d0951d6e0abf850129f776327 Mon Sep 17 00:00:00 2001 From: LukePulverenti Luke Pulverenti luke pulverenti Date: Tue, 31 Jul 2012 12:29:07 -0400 Subject: Added an ApiInteraction project that UI's can use to talk to the server. Moved jsonserializer namespace from json to serialization, since we may be adding an xml serializer. --- .../Serialization/JsonSerializer.cs | 74 ++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 MediaBrowser.Common/Serialization/JsonSerializer.cs (limited to 'MediaBrowser.Common/Serialization') diff --git a/MediaBrowser.Common/Serialization/JsonSerializer.cs b/MediaBrowser.Common/Serialization/JsonSerializer.cs new file mode 100644 index 0000000000..57b285ceea --- /dev/null +++ b/MediaBrowser.Common/Serialization/JsonSerializer.cs @@ -0,0 +1,74 @@ +using System; +using System.IO; + +namespace MediaBrowser.Common.Serialization +{ + /// + /// Provides a wrapper around third party json serialization. + /// + public class JsonSerializer + { + public static void SerializeToStream(T obj, Stream stream) + { + Configure(); + + ServiceStack.Text.JsonSerializer.SerializeToStream(obj, stream); + } + + public static void SerializeToFile(T obj, string file) + { + Configure(); + + using (StreamWriter streamWriter = new StreamWriter(file)) + { + ServiceStack.Text.JsonSerializer.SerializeToWriter(obj, streamWriter); + } + } + + public static object DeserializeFromFile(Type type, string file) + { + Configure(); + + using (Stream stream = File.OpenRead(file)) + { + return ServiceStack.Text.JsonSerializer.DeserializeFromStream(type, stream); + } + } + + public static T DeserializeFromFile(string file) + { + Configure(); + + using (Stream stream = File.OpenRead(file)) + { + return ServiceStack.Text.JsonSerializer.DeserializeFromStream(stream); + } + } + + public static T DeserializeFromStream(Stream stream) + { + Configure(); + + return ServiceStack.Text.JsonSerializer.DeserializeFromStream(stream); + } + + public static T DeserializeFromString(string data) + { + Configure(); + + return ServiceStack.Text.JsonSerializer.DeserializeFromString(data); + } + + private static bool IsConfigured = false; + private static void Configure() + { + if (!IsConfigured) + { + ServiceStack.Text.JsConfig.ExcludeTypeInfo = true; + ServiceStack.Text.JsConfig.IncludeNullValues = false; + + IsConfigured = true; + } + } + } +} -- cgit v1.2.3 From 099ac83cc32033fceca9371d2969bab16f28b6ca Mon Sep 17 00:00:00 2001 From: LukePulverenti Luke Pulverenti luke pulverenti Date: Mon, 13 Aug 2012 10:51:42 -0400 Subject: Added an XmlSerializer to common --- MediaBrowser.Common/MediaBrowser.Common.csproj | 1 + MediaBrowser.Common/Serialization/XmlSerializer.cs | 50 ++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 MediaBrowser.Common/Serialization/XmlSerializer.cs (limited to 'MediaBrowser.Common/Serialization') diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index dc9d807f94..25a855c389 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -77,6 +77,7 @@ + Splash.xaml diff --git a/MediaBrowser.Common/Serialization/XmlSerializer.cs b/MediaBrowser.Common/Serialization/XmlSerializer.cs new file mode 100644 index 0000000000..924a7e8f41 --- /dev/null +++ b/MediaBrowser.Common/Serialization/XmlSerializer.cs @@ -0,0 +1,50 @@ +using System; +using System.IO; + +namespace MediaBrowser.Common.Serialization +{ + /// + /// Provides a wrapper around third party xml serialization. + /// + public class XmlSerializer + { + public static void SerializeToStream(T obj, Stream stream) + { + ServiceStack.Text.XmlSerializer.SerializeToStream(obj, stream); + } + + public static void SerializeToFile(T obj, string file) + { + using (StreamWriter streamWriter = new StreamWriter(file)) + { + ServiceStack.Text.XmlSerializer.SerializeToWriter(obj, streamWriter); + } + } + + public static object DeserializeFromFile(Type type, string file) + { + using (Stream stream = File.OpenRead(file)) + { + return ServiceStack.Text.XmlSerializer.DeserializeFromStream(type, stream); + } + } + + public static T DeserializeFromFile(string file) + { + using (Stream stream = File.OpenRead(file)) + { + return ServiceStack.Text.XmlSerializer.DeserializeFromStream(stream); + } + } + + public static T DeserializeFromStream(Stream stream) + { + return ServiceStack.Text.XmlSerializer.DeserializeFromStream(stream); + } + + public static T DeserializeFromString(string data) + { + return ServiceStack.Text.XmlSerializer.DeserializeFromString(data); + } + } +} -- cgit v1.2.3 From 59a3dcc8c1c6b41560bd48507cfcf4f0ca0a8862 Mon Sep 17 00:00:00 2001 From: LukePulverenti Luke Pulverenti luke pulverenti Date: Sat, 18 Aug 2012 16:38:02 -0400 Subject: Slight re-work of ApplicationPaths so that we can have inherited versions for the UI and Server --- MediaBrowser.Api/ApiService.cs | 2 +- MediaBrowser.Api/HttpHandlers/BaseMediaHandler.cs | 2 +- .../Configuration/ApplicationPaths.cs | 299 --------------------- .../Configuration/BaseApplicationPaths.cs | 133 +++++++++ MediaBrowser.Common/Kernel/BaseKernel.cs | 11 +- MediaBrowser.Common/MediaBrowser.Common.csproj | 2 +- MediaBrowser.Common/Serialization/XmlSerializer.cs | 25 +- .../Configuration/ServerApplicationPaths.cs | 154 +++++++++++ MediaBrowser.Controller/Kernel.cs | 4 +- MediaBrowser.Controller/Library/ItemController.cs | 8 +- .../MediaBrowser.Controller.csproj | 1 + 11 files changed, 312 insertions(+), 329 deletions(-) delete mode 100644 MediaBrowser.Common/Configuration/ApplicationPaths.cs create mode 100644 MediaBrowser.Common/Configuration/BaseApplicationPaths.cs create mode 100644 MediaBrowser.Controller/Configuration/ServerApplicationPaths.cs (limited to 'MediaBrowser.Common/Serialization') diff --git a/MediaBrowser.Api/ApiService.cs b/MediaBrowser.Api/ApiService.cs index 76a93d4bbc..891b728342 100644 --- a/MediaBrowser.Api/ApiService.cs +++ b/MediaBrowser.Api/ApiService.cs @@ -208,7 +208,7 @@ namespace MediaBrowser.Api { if (_FFMpegDirectory == null) { - _FFMpegDirectory = System.IO.Path.Combine(ApplicationPaths.ProgramDataPath, "ffmpeg"); + _FFMpegDirectory = System.IO.Path.Combine(Kernel.Instance.ApplicationPaths.ProgramDataPath, "ffmpeg"); if (!Directory.Exists(_FFMpegDirectory)) { diff --git a/MediaBrowser.Api/HttpHandlers/BaseMediaHandler.cs b/MediaBrowser.Api/HttpHandlers/BaseMediaHandler.cs index fd85993c8e..334dc12b1e 100644 --- a/MediaBrowser.Api/HttpHandlers/BaseMediaHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/BaseMediaHandler.cs @@ -174,7 +174,7 @@ namespace MediaBrowser.Api.HttpHandlers process.StartInfo = startInfo; // FFMpeg writes debug/error info to stderr. This is useful when debugging so let's put it in the log directory. - FileStream logStream = new FileStream(Path.Combine(ApplicationPaths.LogDirectoryPath, "ffmpeg-" + Guid.NewGuid().ToString() + ".txt"), FileMode.Create); + FileStream logStream = new FileStream(Path.Combine(Kernel.Instance.ApplicationPaths.LogDirectoryPath, "ffmpeg-" + Guid.NewGuid().ToString() + ".txt"), FileMode.Create); try { diff --git a/MediaBrowser.Common/Configuration/ApplicationPaths.cs b/MediaBrowser.Common/Configuration/ApplicationPaths.cs deleted file mode 100644 index efe6f0c9e0..0000000000 --- a/MediaBrowser.Common/Configuration/ApplicationPaths.cs +++ /dev/null @@ -1,299 +0,0 @@ -using System.Configuration; -using System.IO; -using System.Reflection; - -namespace MediaBrowser.Common.Configuration -{ - public static class ApplicationPaths - { - private static string _programDataPath; - /// - /// Gets the path to the program data folder - /// - public static string ProgramDataPath - { - get - { - if (_programDataPath == null) - { - _programDataPath = GetProgramDataPath(); - } - return _programDataPath; - } - } - - - private static string _pluginsPath; - /// - /// Gets the path to the plugin directory - /// - public static string PluginsPath - { - get - { - if (_pluginsPath == null) - { - _pluginsPath = Path.Combine(ProgramDataPath, "plugins"); - if (!Directory.Exists(_pluginsPath)) - { - Directory.CreateDirectory(_pluginsPath); - } - } - - return _pluginsPath; - } - } - - private static string _configurationPath; - /// - /// Gets the path to the application configuration root directory - /// - public static string ConfigurationPath - { - get - { - if (_configurationPath == null) - { - _configurationPath = Path.Combine(ProgramDataPath, "config"); - if (!Directory.Exists(_configurationPath)) - { - Directory.CreateDirectory(_configurationPath); - } - } - return _configurationPath; - } - } - - private static string _systemConfigurationPath; - /// - /// Gets the path to the system configuration directory - /// - public static string SystemConfigurationPath - { - get - { - if (_systemConfigurationPath == null) - { - _systemConfigurationPath = Path.Combine(ConfigurationPath, "system"); - if (!Directory.Exists(_systemConfigurationPath)) - { - Directory.CreateDirectory(_systemConfigurationPath); - } - } - return _systemConfigurationPath; - } - } - - private static string _userConfigurationPath; - /// - /// Gets the path to the user configuration directory - /// - public static string UserConfigurationPath - { - get - { - if (_userConfigurationPath == null) - { - _userConfigurationPath = Path.Combine(ConfigurationPath, "user"); - if (!Directory.Exists(_userConfigurationPath)) - { - Directory.CreateDirectory(_userConfigurationPath); - } - } - return _userConfigurationPath; - } - } - - private static string _deviceConfigurationPath; - /// - /// Gets the path to the device configuration directory - /// - public static string DeviceConfigurationPath - { - get - { - if (_deviceConfigurationPath == null) - { - _deviceConfigurationPath = Path.Combine(ConfigurationPath, "device"); - if (!Directory.Exists(_deviceConfigurationPath)) - { - Directory.CreateDirectory(_deviceConfigurationPath); - } - } - return _deviceConfigurationPath; - } - } - - private static string _logDirectoryPath; - /// - /// Gets the path to the log directory - /// - public static string LogDirectoryPath - { - get - { - if (_logDirectoryPath == null) - { - _logDirectoryPath = Path.Combine(ProgramDataPath, "logs"); - if (!Directory.Exists(_logDirectoryPath)) - { - Directory.CreateDirectory(_logDirectoryPath); - } - } - return _logDirectoryPath; - } - } - - private static string _rootFolderPath; - /// - /// Gets the path to the root media directory - /// - public static string RootFolderPath - { - get - { - if (_rootFolderPath == null) - { - _rootFolderPath = Path.Combine(ProgramDataPath, "root"); - if (!Directory.Exists(_rootFolderPath)) - { - Directory.CreateDirectory(_rootFolderPath); - } - } - return _rootFolderPath; - } - } - - private static string _ibnPath; - /// - /// Gets the path to the Images By Name directory - /// - public static string ImagesByNamePath - { - get - { - if (_ibnPath == null) - { - _ibnPath = Path.Combine(ProgramDataPath, "ImagesByName"); - if (!Directory.Exists(_ibnPath)) - { - Directory.CreateDirectory(_ibnPath); - } - } - - return _ibnPath; - } - } - - private static string _PeoplePath; - /// - /// Gets the path to the People directory - /// - public static string PeoplePath - { - get - { - if (_PeoplePath == null) - { - _PeoplePath = Path.Combine(ImagesByNamePath, "People"); - if (!Directory.Exists(_PeoplePath)) - { - Directory.CreateDirectory(_PeoplePath); - } - } - - return _PeoplePath; - } - } - - private static string _GenrePath; - /// - /// Gets the path to the Genre directory - /// - public static string GenrePath - { - get - { - if (_GenrePath == null) - { - _GenrePath = Path.Combine(ImagesByNamePath, "Genre"); - if (!Directory.Exists(_GenrePath)) - { - Directory.CreateDirectory(_GenrePath); - } - } - - return _GenrePath; - } - } - - private static string _StudioPath; - /// - /// Gets the path to the Studio directory - /// - public static string StudioPath - { - get - { - if (_StudioPath == null) - { - _StudioPath = Path.Combine(ImagesByNamePath, "Studio"); - if (!Directory.Exists(_StudioPath)) - { - Directory.CreateDirectory(_StudioPath); - } - } - - return _StudioPath; - } - } - - private static string _yearPath; - /// - /// Gets the path to the Year directory - /// - public static string YearPath - { - get - { - if (_yearPath == null) - { - _yearPath = Path.Combine(ImagesByNamePath, "Year"); - if (!Directory.Exists(_yearPath)) - { - Directory.CreateDirectory(_yearPath); - } - } - - return _yearPath; - } - } - - /// - /// Gets the path to the application's ProgramDataFolder - /// - private static string GetProgramDataPath() - { - string programDataPath = ConfigurationManager.AppSettings["ProgramDataPath"]; - - // If it's a relative path, e.g. "..\" - if (!Path.IsPathRooted(programDataPath)) - { - string path = Assembly.GetExecutingAssembly().Location; - path = Path.GetDirectoryName(path); - - programDataPath = Path.Combine(path, programDataPath); - - programDataPath = Path.GetFullPath(programDataPath); - } - - if (!Directory.Exists(programDataPath)) - { - Directory.CreateDirectory(programDataPath); - } - - return programDataPath; - } - - } -} diff --git a/MediaBrowser.Common/Configuration/BaseApplicationPaths.cs b/MediaBrowser.Common/Configuration/BaseApplicationPaths.cs new file mode 100644 index 0000000000..ae45280136 --- /dev/null +++ b/MediaBrowser.Common/Configuration/BaseApplicationPaths.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.IO; +using System.Configuration; +using System.Reflection; + +namespace MediaBrowser.Common.Configuration +{ + public abstract class BaseApplicationPaths + { + private string _programDataPath; + /// + /// Gets the path to the program data folder + /// + public string ProgramDataPath + { + get + { + if (_programDataPath == null) + { + _programDataPath = GetProgramDataPath(); + } + return _programDataPath; + } + } + + private string _pluginsPath; + /// + /// Gets the path to the plugin directory + /// + public string PluginsPath + { + get + { + if (_pluginsPath == null) + { + _pluginsPath = Path.Combine(ProgramDataPath, "plugins"); + if (!Directory.Exists(_pluginsPath)) + { + Directory.CreateDirectory(_pluginsPath); + } + } + + return _pluginsPath; + } + } + + private string _logDirectoryPath; + /// + /// Gets the path to the log directory + /// + public string LogDirectoryPath + { + get + { + if (_logDirectoryPath == null) + { + _logDirectoryPath = Path.Combine(ProgramDataPath, "logs"); + if (!Directory.Exists(_logDirectoryPath)) + { + Directory.CreateDirectory(_logDirectoryPath); + } + } + return _logDirectoryPath; + } + } + + private string _configurationDirectoryPath; + /// + /// Gets the path to the application configuration root directory + /// + public string ConfigurationDirectoryPath + { + get + { + if (_configurationDirectoryPath == null) + { + _configurationDirectoryPath = Path.Combine(ProgramDataPath, "config"); + if (!Directory.Exists(_configurationDirectoryPath)) + { + Directory.CreateDirectory(_configurationDirectoryPath); + } + } + return _configurationDirectoryPath; + } + } + + private string _systemConfigurationFilePath; + /// + /// Gets the path to the system configuration file + /// + public string SystemConfigurationFilePath + { + get + { + if (_systemConfigurationFilePath == null) + { + _systemConfigurationFilePath = Path.Combine(ConfigurationDirectoryPath, "system.xml"); + } + return _systemConfigurationFilePath; + } + } + + /// + /// Gets the path to the application's ProgramDataFolder + /// + private static string GetProgramDataPath() + { + string programDataPath = ConfigurationManager.AppSettings["ProgramDataPath"]; + + // If it's a relative path, e.g. "..\" + if (!Path.IsPathRooted(programDataPath)) + { + string path = Assembly.GetExecutingAssembly().Location; + path = Path.GetDirectoryName(path); + + programDataPath = Path.Combine(path, programDataPath); + + programDataPath = Path.GetFullPath(programDataPath); + } + + if (!Directory.Exists(programDataPath)) + { + Directory.CreateDirectory(programDataPath); + } + + return programDataPath; + } + } +} diff --git a/MediaBrowser.Common/Kernel/BaseKernel.cs b/MediaBrowser.Common/Kernel/BaseKernel.cs index 6e24fcfc27..ecfe11e2cb 100644 --- a/MediaBrowser.Common/Kernel/BaseKernel.cs +++ b/MediaBrowser.Common/Kernel/BaseKernel.cs @@ -18,14 +18,17 @@ namespace MediaBrowser.Common.Kernel /// /// Represents a shared base kernel for both the UI and server apps /// - public abstract class BaseKernel : IDisposable + public abstract class BaseKernel : IDisposable where TConfigurationType : BaseApplicationConfiguration, new() + where TApplicationPathsType : BaseApplicationPaths, new() { /// /// Gets the current configuration /// public TConfigurationType Configuration { get; private set; } + public TApplicationPathsType ApplicationPaths { get; private set; } + /// /// Gets the list of currently loaded plugins /// @@ -45,7 +48,7 @@ namespace MediaBrowser.Common.Kernel public BaseKernel() { - + ApplicationPaths = new TApplicationPathsType(); } public virtual void Init(IProgress progress) @@ -149,13 +152,13 @@ namespace MediaBrowser.Common.Kernel //Configuration information for anything other than server-specific configuration will have to come via the API... -ebr // Deserialize config - if (!File.Exists(ApplicationPaths.ConfigurationPath)) + if (!File.Exists(ApplicationPaths.SystemConfigurationFilePath)) { Configuration = new TConfigurationType(); } else { - Configuration = JsonSerializer.DeserializeFromFile(ApplicationPaths.ConfigurationPath); + Configuration = XmlSerializer.DeserializeFromFile(ApplicationPaths.SystemConfigurationFilePath); } Logger.LoggerInstance.LogSeverity = Configuration.LogSeverity; diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 691787f1cd..f7ccc17786 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -61,8 +61,8 @@ - + diff --git a/MediaBrowser.Common/Serialization/XmlSerializer.cs b/MediaBrowser.Common/Serialization/XmlSerializer.cs index 924a7e8f41..45c416f3b0 100644 --- a/MediaBrowser.Common/Serialization/XmlSerializer.cs +++ b/MediaBrowser.Common/Serialization/XmlSerializer.cs @@ -1,5 +1,4 @@ -using System; -using System.IO; +using System.IO; namespace MediaBrowser.Common.Serialization { @@ -10,22 +9,14 @@ namespace MediaBrowser.Common.Serialization { public static void SerializeToStream(T obj, Stream stream) { - ServiceStack.Text.XmlSerializer.SerializeToStream(obj, stream); + GetSerializer().Serialize(stream, obj); } public static void SerializeToFile(T obj, string file) { - using (StreamWriter streamWriter = new StreamWriter(file)) + using (FileStream stream = new FileStream(file, FileMode.Create)) { - ServiceStack.Text.XmlSerializer.SerializeToWriter(obj, streamWriter); - } - } - - public static object DeserializeFromFile(Type type, string file) - { - using (Stream stream = File.OpenRead(file)) - { - return ServiceStack.Text.XmlSerializer.DeserializeFromStream(type, stream); + GetSerializer().Serialize(stream, obj); } } @@ -33,18 +24,18 @@ namespace MediaBrowser.Common.Serialization { using (Stream stream = File.OpenRead(file)) { - return ServiceStack.Text.XmlSerializer.DeserializeFromStream(stream); + return (T)GetSerializer().Deserialize(stream); } } public static T DeserializeFromStream(Stream stream) { - return ServiceStack.Text.XmlSerializer.DeserializeFromStream(stream); + return (T)GetSerializer().Deserialize(stream); } - public static T DeserializeFromString(string data) + private static System.Xml.Serialization.XmlSerializer GetSerializer() { - return ServiceStack.Text.XmlSerializer.DeserializeFromString(data); + return new System.Xml.Serialization.XmlSerializer(typeof(T)); } } } diff --git a/MediaBrowser.Controller/Configuration/ServerApplicationPaths.cs b/MediaBrowser.Controller/Configuration/ServerApplicationPaths.cs new file mode 100644 index 0000000000..bd33b19842 --- /dev/null +++ b/MediaBrowser.Controller/Configuration/ServerApplicationPaths.cs @@ -0,0 +1,154 @@ +using System.IO; +using MediaBrowser.Common.Configuration; + +namespace MediaBrowser.Controller.Configuration +{ + public class ServerApplicationPaths : BaseApplicationPaths + { + private string _rootFolderPath; + /// + /// Gets the path to the root media directory + /// + public string RootFolderPath + { + get + { + if (_rootFolderPath == null) + { + _rootFolderPath = Path.Combine(ProgramDataPath, "root"); + if (!Directory.Exists(_rootFolderPath)) + { + Directory.CreateDirectory(_rootFolderPath); + } + } + return _rootFolderPath; + } + } + + private string _ibnPath; + /// + /// Gets the path to the Images By Name directory + /// + public string ImagesByNamePath + { + get + { + if (_ibnPath == null) + { + _ibnPath = Path.Combine(ProgramDataPath, "ImagesByName"); + if (!Directory.Exists(_ibnPath)) + { + Directory.CreateDirectory(_ibnPath); + } + } + + return _ibnPath; + } + } + + private string _PeoplePath; + /// + /// Gets the path to the People directory + /// + public string PeoplePath + { + get + { + if (_PeoplePath == null) + { + _PeoplePath = Path.Combine(ImagesByNamePath, "People"); + if (!Directory.Exists(_PeoplePath)) + { + Directory.CreateDirectory(_PeoplePath); + } + } + + return _PeoplePath; + } + } + + private string _GenrePath; + /// + /// Gets the path to the Genre directory + /// + public string GenrePath + { + get + { + if (_GenrePath == null) + { + _GenrePath = Path.Combine(ImagesByNamePath, "Genre"); + if (!Directory.Exists(_GenrePath)) + { + Directory.CreateDirectory(_GenrePath); + } + } + + return _GenrePath; + } + } + + private string _StudioPath; + /// + /// Gets the path to the Studio directory + /// + public string StudioPath + { + get + { + if (_StudioPath == null) + { + _StudioPath = Path.Combine(ImagesByNamePath, "Studio"); + if (!Directory.Exists(_StudioPath)) + { + Directory.CreateDirectory(_StudioPath); + } + } + + return _StudioPath; + } + } + + private string _yearPath; + /// + /// Gets the path to the Year directory + /// + public string YearPath + { + get + { + if (_yearPath == null) + { + _yearPath = Path.Combine(ImagesByNamePath, "Year"); + if (!Directory.Exists(_yearPath)) + { + Directory.CreateDirectory(_yearPath); + } + } + + return _yearPath; + } + } + + private string _userConfigurationDirectoryPath; + /// + /// Gets the path to the user configuration directory + /// + public string UserConfigurationDirectoryPath + { + get + { + if (_userConfigurationDirectoryPath == null) + { + _userConfigurationDirectoryPath = Path.Combine(ConfigurationDirectoryPath, "user"); + if (!Directory.Exists(_userConfigurationDirectoryPath)) + { + Directory.CreateDirectory(_userConfigurationDirectoryPath); + } + } + return _userConfigurationDirectoryPath; + } + } + + } +} diff --git a/MediaBrowser.Controller/Kernel.cs b/MediaBrowser.Controller/Kernel.cs index 2058f6d611..a9e536c7bd 100644 --- a/MediaBrowser.Controller/Kernel.cs +++ b/MediaBrowser.Controller/Kernel.cs @@ -17,7 +17,7 @@ using MediaBrowser.Model.Progress; namespace MediaBrowser.Controller { - public class Kernel : BaseKernel + public class Kernel : BaseKernel { public static Kernel Instance { get; private set; } @@ -43,7 +43,7 @@ namespace MediaBrowser.Controller public IEnumerable EntityResolvers { get; private set; } /// - /// Creates a kernal based on a Data path, which is akin to our current programdata path + /// Creates a kernel based on a Data path, which is akin to our current programdata path /// public Kernel() : base() diff --git a/MediaBrowser.Controller/Library/ItemController.cs b/MediaBrowser.Controller/Library/ItemController.cs index 10648eca09..8d269679f5 100644 --- a/MediaBrowser.Controller/Library/ItemController.cs +++ b/MediaBrowser.Controller/Library/ItemController.cs @@ -305,7 +305,7 @@ namespace MediaBrowser.Controller.Library /// public Person GetPerson(string name) { - string path = Path.Combine(ApplicationPaths.PeoplePath, name); + string path = Path.Combine(Kernel.Instance.ApplicationPaths.PeoplePath, name); return GetImagesByNameItem(path, name); } @@ -315,7 +315,7 @@ namespace MediaBrowser.Controller.Library /// public Studio GetStudio(string name) { - string path = Path.Combine(ApplicationPaths.StudioPath, name); + string path = Path.Combine(Kernel.Instance.ApplicationPaths.StudioPath, name); return GetImagesByNameItem(path, name); } @@ -325,7 +325,7 @@ namespace MediaBrowser.Controller.Library /// public Genre GetGenre(string name) { - string path = Path.Combine(ApplicationPaths.GenrePath, name); + string path = Path.Combine(Kernel.Instance.ApplicationPaths.GenrePath, name); return GetImagesByNameItem(path, name); } @@ -335,7 +335,7 @@ namespace MediaBrowser.Controller.Library /// public Year GetYear(int value) { - string path = Path.Combine(ApplicationPaths.YearPath, value.ToString()); + string path = Path.Combine(Kernel.Instance.ApplicationPaths.YearPath, value.ToString()); return GetImagesByNameItem(path, value.ToString()); } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 5c60529710..3000fd7a06 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -49,6 +49,7 @@ + -- cgit v1.2.3 From 020c20bd7d8503d2acdaa1b3c495f1d7f7785636 Mon Sep 17 00:00:00 2001 From: LukePulverenti Luke Pulverenti luke pulverenti Date: Wed, 22 Aug 2012 09:19:18 -0400 Subject: Added support for jsv format output from the api --- MediaBrowser.Common/MediaBrowser.Common.csproj | 3 +- .../Net/Handlers/BaseJsonHandler.cs | 46 ------------ .../Net/Handlers/BaseSerializationHandler.cs | 83 ++++++++++++++++++++++ MediaBrowser.Common/Serialization/JsvSerializer.cs | 22 ++++++ 4 files changed, 107 insertions(+), 47 deletions(-) delete mode 100644 MediaBrowser.Common/Net/Handlers/BaseJsonHandler.cs create mode 100644 MediaBrowser.Common/Net/Handlers/BaseSerializationHandler.cs create mode 100644 MediaBrowser.Common/Serialization/JsvSerializer.cs (limited to 'MediaBrowser.Common/Serialization') diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 57c817fc2c..7c736affb4 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -83,11 +83,12 @@ - + + diff --git a/MediaBrowser.Common/Net/Handlers/BaseJsonHandler.cs b/MediaBrowser.Common/Net/Handlers/BaseJsonHandler.cs deleted file mode 100644 index 6508535376..0000000000 --- a/MediaBrowser.Common/Net/Handlers/BaseJsonHandler.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.IO; -using System.Threading.Tasks; -using MediaBrowser.Common.Serialization; - -namespace MediaBrowser.Common.Net.Handlers -{ - public abstract class BaseJsonHandler : BaseHandler - { - public override Task GetContentType() - { - return Task.FromResult(MimeTypes.JsonMimeType); - } - - private bool _ObjectToSerializeEnsured = false; - private T _ObjectToSerialize; - - private async Task EnsureObjectToSerialize() - { - if (!_ObjectToSerializeEnsured) - { - _ObjectToSerialize = await GetObjectToSerialize().ConfigureAwait(false); - - if (_ObjectToSerialize == null) - { - StatusCode = 404; - } - - _ObjectToSerializeEnsured = true; - } - } - - protected abstract Task GetObjectToSerialize(); - - protected override Task PrepareResponse() - { - return EnsureObjectToSerialize(); - } - - protected async override Task WriteResponseToOutputStream(Stream stream) - { - await EnsureObjectToSerialize(); - - JsonSerializer.SerializeToStream(_ObjectToSerialize, stream); - } - } -} diff --git a/MediaBrowser.Common/Net/Handlers/BaseSerializationHandler.cs b/MediaBrowser.Common/Net/Handlers/BaseSerializationHandler.cs new file mode 100644 index 0000000000..4229dce613 --- /dev/null +++ b/MediaBrowser.Common/Net/Handlers/BaseSerializationHandler.cs @@ -0,0 +1,83 @@ +using System.IO; +using System.Threading.Tasks; +using MediaBrowser.Common.Serialization; +using System; + +namespace MediaBrowser.Common.Net.Handlers +{ + public abstract class BaseJsonHandler : BaseHandler + { + public SerializationFormat SerializationFormat + { + get + { + string format = QueryString["dataformat"]; + + if (string.IsNullOrEmpty(format)) + { + return Handlers.SerializationFormat.Json; + } + + return (SerializationFormat)Enum.Parse(typeof(SerializationFormat), format, true); + } + } + + public override Task GetContentType() + { + switch (SerializationFormat) + { + case Handlers.SerializationFormat.Jsv: + return Task.FromResult("text/plain"); + default: + return Task.FromResult(MimeTypes.JsonMimeType); + } + } + + private bool _ObjectToSerializeEnsured = false; + private T _ObjectToSerialize; + + private async Task EnsureObjectToSerialize() + { + if (!_ObjectToSerializeEnsured) + { + _ObjectToSerialize = await GetObjectToSerialize().ConfigureAwait(false); + + if (_ObjectToSerialize == null) + { + StatusCode = 404; + } + + _ObjectToSerializeEnsured = true; + } + } + + protected abstract Task GetObjectToSerialize(); + + protected override Task PrepareResponse() + { + return EnsureObjectToSerialize(); + } + + protected async override Task WriteResponseToOutputStream(Stream stream) + { + await EnsureObjectToSerialize(); + + switch (SerializationFormat) + { + case Handlers.SerializationFormat.Jsv: + JsvSerializer.SerializeToStream(_ObjectToSerialize, stream); + break; + default: + JsonSerializer.SerializeToStream(_ObjectToSerialize, stream); + break; + } + } + } + + public enum SerializationFormat + { + Json, + Jsv + } + +} diff --git a/MediaBrowser.Common/Serialization/JsvSerializer.cs b/MediaBrowser.Common/Serialization/JsvSerializer.cs new file mode 100644 index 0000000000..c643d41b0f --- /dev/null +++ b/MediaBrowser.Common/Serialization/JsvSerializer.cs @@ -0,0 +1,22 @@ +using System.IO; + +namespace MediaBrowser.Common.Serialization +{ + /// + /// This adds support for ServiceStack's proprietary JSV output format. + /// It's based on Json but the serializer performs faster and output runs about 10% smaller + /// http://www.servicestack.net/benchmarks/NorthwindDatabaseRowsSerialization.100000-times.2010-08-17.html + /// + public static class JsvSerializer + { + public static void SerializeToStream(T obj, Stream stream) + { + ServiceStack.Text.TypeSerializer.SerializeToStream(obj, stream); + } + + public static T DeserializeFromStream(Stream stream) + { + return ServiceStack.Text.TypeSerializer.DeserializeFromStream(stream); + } + } +} -- cgit v1.2.3 From a2f120b76b4e5192b7d104e505f70921caa64f93 Mon Sep 17 00:00:00 2001 From: LukePulverenti Luke Pulverenti luke pulverenti Date: Wed, 22 Aug 2012 13:01:05 -0400 Subject: Tweaked json and jsv serializers --- MediaBrowser.Common/Serialization/JsonSerializer.cs | 11 ++--------- MediaBrowser.Common/Serialization/JsvSerializer.cs | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 9 deletions(-) (limited to 'MediaBrowser.Common/Serialization') diff --git a/MediaBrowser.Common/Serialization/JsonSerializer.cs b/MediaBrowser.Common/Serialization/JsonSerializer.cs index 57b285ceea..e73048f176 100644 --- a/MediaBrowser.Common/Serialization/JsonSerializer.cs +++ b/MediaBrowser.Common/Serialization/JsonSerializer.cs @@ -19,9 +19,9 @@ namespace MediaBrowser.Common.Serialization { Configure(); - using (StreamWriter streamWriter = new StreamWriter(file)) + using (Stream stream = File.Open(file, FileMode.Create)) { - ServiceStack.Text.JsonSerializer.SerializeToWriter(obj, streamWriter); + ServiceStack.Text.JsonSerializer.SerializeToStream(obj, stream); } } @@ -52,13 +52,6 @@ namespace MediaBrowser.Common.Serialization return ServiceStack.Text.JsonSerializer.DeserializeFromStream(stream); } - public static T DeserializeFromString(string data) - { - Configure(); - - return ServiceStack.Text.JsonSerializer.DeserializeFromString(data); - } - private static bool IsConfigured = false; private static void Configure() { diff --git a/MediaBrowser.Common/Serialization/JsvSerializer.cs b/MediaBrowser.Common/Serialization/JsvSerializer.cs index c643d41b0f..d2a12e0598 100644 --- a/MediaBrowser.Common/Serialization/JsvSerializer.cs +++ b/MediaBrowser.Common/Serialization/JsvSerializer.cs @@ -18,5 +18,21 @@ namespace MediaBrowser.Common.Serialization { return ServiceStack.Text.TypeSerializer.DeserializeFromStream(stream); } + + public static void SerializeToFile(T obj, string file) + { + using (Stream stream = File.Open(file, FileMode.Create)) + { + ServiceStack.Text.TypeSerializer.SerializeToStream(obj, stream); + } + } + + public static T DeserializeFromFile(string file) + { + using (Stream stream = File.OpenRead(file)) + { + return ServiceStack.Text.TypeSerializer.DeserializeFromStream(stream); + } + } } } -- cgit v1.2.3 From c80c8c1cfd594f2597e46b09d44360ade9f4fec2 Mon Sep 17 00:00:00 2001 From: LukePulverenti Luke Pulverenti luke pulverenti Date: Thu, 23 Aug 2012 01:45:26 -0400 Subject: Switched all i/o to win32 methods and added protobuf serialization for ffprobe caching --- MediaBrowser.Common/MediaBrowser.Common.csproj | 4 + .../Serialization/ProtobufSerializer.cs | 38 ++++++++++ MediaBrowser.Common/UI/BaseApplication.cs | 5 ++ MediaBrowser.Common/packages.config | 1 + .../Events/ItemResolveEventArgs.cs | 86 ++++++++++------------ MediaBrowser.Controller/FFMpeg/FFProbe.cs | 40 +++++----- MediaBrowser.Controller/FFMpeg/FFProbeResult.cs | 59 ++++++++++++++- MediaBrowser.Controller/IO/FileData.cs | 84 ++++++++++++++------- MediaBrowser.Controller/Kernel.cs | 6 +- MediaBrowser.Controller/Library/ItemController.cs | 71 +++++++----------- .../MediaBrowser.Controller.csproj | 4 + .../Providers/FolderProviderFromXml.cs | 7 +- .../Providers/LocalTrailerProvider.cs | 19 ++--- .../Providers/VideoInfoProvider.cs | 4 + .../Resolvers/BaseItemResolver.cs | 18 ++--- MediaBrowser.Controller/Resolvers/VideoResolver.cs | 2 +- MediaBrowser.Controller/packages.config | 1 + .../Providers/MovieProviderFromXml.cs | 7 +- MediaBrowser.Movies/Resolvers/MovieResolver.cs | 38 +++++----- MediaBrowser.TV/Providers/SeriesProviderFromXml.cs | 7 +- MediaBrowser.TV/Resolvers/SeriesResolver.cs | 4 +- MediaBrowser.TV/TVUtils.cs | 4 +- 22 files changed, 309 insertions(+), 200 deletions(-) create mode 100644 MediaBrowser.Common/Serialization/ProtobufSerializer.cs (limited to 'MediaBrowser.Common/Serialization') diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 7c736affb4..c38847b5c1 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -33,6 +33,9 @@ + + ..\packages\protobuf-net.2.0.0.480\lib\net40\protobuf-net.dll + False ..\packages\ServiceStack.Text.3.9.5\lib\net35\ServiceStack.Text.dll @@ -89,6 +92,7 @@ + diff --git a/MediaBrowser.Common/Serialization/ProtobufSerializer.cs b/MediaBrowser.Common/Serialization/ProtobufSerializer.cs new file mode 100644 index 0000000000..9737c9b59d --- /dev/null +++ b/MediaBrowser.Common/Serialization/ProtobufSerializer.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.IO; + +namespace MediaBrowser.Common.Serialization +{ + public static class ProtobufSerializer + { + public static void SerializeToStream(T obj, Stream stream) + { + ProtoBuf.Serializer.Serialize(stream, obj); + } + + public static T DeserializeFromStream(Stream stream) + { + return ProtoBuf.Serializer.Deserialize(stream); + } + + public static void SerializeToFile(T obj, string file) + { + using (Stream stream = File.Open(file, FileMode.Create)) + { + SerializeToStream(obj, stream); + } + } + + public static T DeserializeFromFile(string file) + { + using (Stream stream = File.OpenRead(file)) + { + return DeserializeFromStream(stream); + } + } + } +} diff --git a/MediaBrowser.Common/UI/BaseApplication.cs b/MediaBrowser.Common/UI/BaseApplication.cs index 27c64f4519..b526781dfe 100644 --- a/MediaBrowser.Common/UI/BaseApplication.cs +++ b/MediaBrowser.Common/UI/BaseApplication.cs @@ -48,6 +48,11 @@ namespace MediaBrowser.Common.UI } catch (Exception ex) { + if (Logger.LoggerInstance != null) + { + Logger.LogException(ex); + } + MessageBox.Show("There was an error launching Media Browser: " + ex.Message); splash.Close(); diff --git a/MediaBrowser.Common/packages.config b/MediaBrowser.Common/packages.config index 6d863a76a8..a4e0c98174 100644 --- a/MediaBrowser.Common/packages.config +++ b/MediaBrowser.Common/packages.config @@ -1,5 +1,6 @@  + diff --git a/MediaBrowser.Controller/Events/ItemResolveEventArgs.cs b/MediaBrowser.Controller/Events/ItemResolveEventArgs.cs index 72eebc5f66..7251e3ec9e 100644 --- a/MediaBrowser.Controller/Events/ItemResolveEventArgs.cs +++ b/MediaBrowser.Controller/Events/ItemResolveEventArgs.cs @@ -10,70 +10,47 @@ namespace MediaBrowser.Controller.Events /// public class ItemResolveEventArgs : PreBeginResolveEventArgs { - public LazyFileInfo[] FileSystemChildren { get; set; } + public WIN32_FIND_DATA[] FileSystemChildren { get; set; } - public LazyFileInfo? GetFileSystemEntry(string path, bool? isFolder = null) + public WIN32_FIND_DATA? GetFileSystemEntry(string path) { for (int i = 0; i < FileSystemChildren.Length; i++) { - LazyFileInfo entry = FileSystemChildren[i]; + WIN32_FIND_DATA entry = FileSystemChildren[i]; if (entry.Path.Equals(path, StringComparison.OrdinalIgnoreCase)) { - if (isFolder.HasValue) - { - if (isFolder.Value && !entry.FileInfo.IsDirectory) - { - continue; - } - else if (!isFolder.Value && entry.FileInfo.IsDirectory) - { - continue; - } - } - return entry; } } - + return null; } - public LazyFileInfo? GetFileSystemEntryByName(string name, bool? isFolder = null) + public bool ContainsFile(string name) { for (int i = 0; i < FileSystemChildren.Length; i++) { - LazyFileInfo entry = FileSystemChildren[i]; - - if (System.IO.Path.GetFileName(entry.Path).Equals(name, StringComparison.OrdinalIgnoreCase)) + if (System.IO.Path.GetFileName(FileSystemChildren[i].Path).Equals(name, StringComparison.OrdinalIgnoreCase)) { - if (isFolder.HasValue) - { - if (isFolder.Value && !entry.FileInfo.IsDirectory) - { - continue; - } - else if (!isFolder.Value && entry.FileInfo.IsDirectory) - { - continue; - } - } - - return entry; + return true; } } - return null; - } - - public bool ContainsFile(string name) - { - return GetFileSystemEntryByName(name, false) != null; + return false; } public bool ContainsFolder(string name) { - return GetFileSystemEntryByName(name, true) != null; + for (int i = 0; i < FileSystemChildren.Length; i++) + { + if (System.IO.Path.GetFileName(FileSystemChildren[i].Path).Equals(name, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + } + + return false; } } @@ -88,21 +65,15 @@ namespace MediaBrowser.Controller.Events public bool Cancel { get; set; } - public LazyFileInfo File { get; set; } + public WIN32_FIND_DATA FileInfo { get; set; } - public string Path - { - get - { - return File.Path; - } - } + public string Path { get; set; } public bool IsDirectory { get { - return File.FileInfo.dwFileAttributes.HasFlag(FileAttributes.Directory); + return FileInfo.dwFileAttributes.HasFlag(FileAttributes.Directory); } } @@ -133,5 +104,22 @@ namespace MediaBrowser.Controller.Events return vf.CollectionType; } } + + public bool IsHidden + { + get + { + return FileInfo.IsHidden; + } + } + + public bool IsSystemFile + { + get + { + return FileInfo.IsSystemFile; + } + } + } } diff --git a/MediaBrowser.Controller/FFMpeg/FFProbe.cs b/MediaBrowser.Controller/FFMpeg/FFProbe.cs index eb0d77a998..83f70af3ad 100644 --- a/MediaBrowser.Controller/FFMpeg/FFProbe.cs +++ b/MediaBrowser.Controller/FFMpeg/FFProbe.cs @@ -23,6 +23,10 @@ namespace MediaBrowser.Controller.FFMpeg catch (FileNotFoundException) { } + catch (Exception ex) + { + Logger.LogException(ex); + } FFProbeResult result = Run(item.Path); @@ -34,15 +38,22 @@ namespace MediaBrowser.Controller.FFMpeg private static FFProbeResult GetCachedResult(string path) { - return JsvSerializer.DeserializeFromFile(path); + return ProtobufSerializer.DeserializeFromFile(path); } - private static void CacheResult(FFProbeResult result, string outputCachePath) + private static async void CacheResult(FFProbeResult result, string outputCachePath) { - Task.Run(() => + await Task.Run(() => { - JsvSerializer.SerializeToFile(result, outputCachePath); - }); + try + { + ProtobufSerializer.SerializeToFile(result, outputCachePath); + } + catch (Exception ex) + { + Logger.LogException(ex); + } + }).ConfigureAwait(false); } public static FFProbeResult Run(Video item) @@ -55,6 +66,10 @@ namespace MediaBrowser.Controller.FFMpeg catch (FileNotFoundException) { } + catch (Exception ex) + { + Logger.LogException(ex); + } FFProbeResult result = Run(item.Path); @@ -93,16 +108,7 @@ namespace MediaBrowser.Controller.FFMpeg // If we ever decide to disable the ffmpeg log then you must uncomment the below line. process.BeginErrorReadLine(); - FFProbeResult result = JsonSerializer.DeserializeFromStream(process.StandardOutput.BaseStream); - - process.WaitForExit(); - - if (process.ExitCode != 0) - { - Logger.LogInfo("FFProbe exited with code {0} for {1}", process.ExitCode, input); - } - - return result; + return JsonSerializer.DeserializeFromStream(process.StandardOutput.BaseStream); } catch (Exception ex) { @@ -129,14 +135,14 @@ namespace MediaBrowser.Controller.FFMpeg { string outputDirectory = Path.Combine(Kernel.Instance.ApplicationPaths.FFProbeAudioCacheDirectory, item.Id.ToString().Substring(0, 1)); - return Path.Combine(outputDirectory, item.Id + "-" + item.DateModified.Ticks + ".jsv"); + return Path.Combine(outputDirectory, item.Id + "-" + item.DateModified.Ticks + ".pb"); } private static string GetFFProbeVideoCachePath(BaseEntity item) { string outputDirectory = Path.Combine(Kernel.Instance.ApplicationPaths.FFProbeVideoCacheDirectory, item.Id.ToString().Substring(0, 1)); - return Path.Combine(outputDirectory, item.Id + "-" + item.DateModified.Ticks + ".jsv"); + return Path.Combine(outputDirectory, item.Id + "-" + item.DateModified.Ticks + ".pb"); } } } diff --git a/MediaBrowser.Controller/FFMpeg/FFProbeResult.cs b/MediaBrowser.Controller/FFMpeg/FFProbeResult.cs index 8b2a8687e9..db7c9dd3c5 100644 --- a/MediaBrowser.Controller/FFMpeg/FFProbeResult.cs +++ b/MediaBrowser.Controller/FFMpeg/FFProbeResult.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using ProtoBuf; namespace MediaBrowser.Controller.FFMpeg { @@ -7,9 +8,13 @@ namespace MediaBrowser.Controller.FFMpeg /// Sample output: /// http://stackoverflow.com/questions/7708373/get-ffmpeg-information-in-friendly-way /// + [ProtoContract] public class FFProbeResult { - public IEnumerable streams { get; set; } + [ProtoMember(1)] + public MediaStream[] streams { get; set; } + + [ProtoMember(2)] public MediaFormat format { get; set; } } @@ -18,47 +23,97 @@ namespace MediaBrowser.Controller.FFMpeg /// A number of properties are commented out to improve deserialization performance /// Enable them as needed. /// + [ProtoContract] public class MediaStream { + [ProtoMember(1)] public int index { get; set; } + + [ProtoMember(2)] public string profile { get; set; } + + [ProtoMember(3)] public string codec_name { get; set; } + + [ProtoMember(4)] public string codec_long_name { get; set; } + + [ProtoMember(5)] public string codec_type { get; set; } + //public string codec_time_base { get; set; } //public string codec_tag { get; set; } //public string codec_tag_string { get; set; } //public string sample_fmt { get; set; } + + [ProtoMember(6)] public string sample_rate { get; set; } + + [ProtoMember(7)] public int channels { get; set; } + //public int bits_per_sample { get; set; } //public string r_frame_rate { get; set; } + + [ProtoMember(8)] public string avg_frame_rate { get; set; } + //public string time_base { get; set; } //public string start_time { get; set; } + + [ProtoMember(9)] public string duration { get; set; } + + [ProtoMember(10)] public string bit_rate { get; set; } + [ProtoMember(11)] public int width { get; set; } + + [ProtoMember(12)] public int height { get; set; } + //public int has_b_frames { get; set; } //public string sample_aspect_ratio { get; set; } + + [ProtoMember(13)] public string display_aspect_ratio { get; set; } + //public string pix_fmt { get; set; } //public int level { get; set; } - public Dictionary tags { get; set; } + + [ProtoMember(14)] + public Dictionary tags { get; set; } } + [ProtoContract] public class MediaFormat { + [ProtoMember(1)] public string filename { get; set; } + + [ProtoMember(2)] public int nb_streams { get; set; } + + [ProtoMember(3)] public string format_name { get; set; } + + [ProtoMember(4)] public string format_long_name { get; set; } + + [ProtoMember(5)] public string start_time { get; set; } + + [ProtoMember(6)] public string duration { get; set; } + + [ProtoMember(7)] public string size { get; set; } + + [ProtoMember(8)] public string bit_rate { get; set; } + + [ProtoMember(9)] public Dictionary tags { get; set; } } } diff --git a/MediaBrowser.Controller/IO/FileData.cs b/MediaBrowser.Controller/IO/FileData.cs index 98332c7949..eca166ead4 100644 --- a/MediaBrowser.Controller/IO/FileData.cs +++ b/MediaBrowser.Controller/IO/FileData.cs @@ -2,6 +2,11 @@ using System.IO; using System.Runtime.InteropServices; +using System.Runtime.ConstrainedExecution; +using Microsoft.Win32.SafeHandles; +using System.Collections.Generic; +using System.Linq; + namespace MediaBrowser.Controller.IO { public static class FileData @@ -16,16 +21,67 @@ namespace MediaBrowser.Controller.IO if (handle == IntPtr.Zero) throw new IOException("FindFirstFile failed"); FindClose(handle); + + data.Path = fileName; return data; } - [DllImport("kernel32")] + public static IEnumerable GetFileSystemEntries(string path, string searchPattern) + { + string lpFileName = Path.Combine(path, searchPattern); + + WIN32_FIND_DATA lpFindFileData; + var handle = FindFirstFile(lpFileName, out lpFindFileData); + + if (handle == IntPtr.Zero) + { + int hr = Marshal.GetLastWin32Error(); + if (hr != 2 && hr != 0x12) + { + throw new IOException("GetFileSystemEntries failed"); + } + yield break; + } + + if (IsValid(lpFindFileData.cFileName)) + { + yield return lpFindFileData; + } + + while (FindNextFile(handle, out lpFindFileData) != IntPtr.Zero) + { + if (IsValid(lpFindFileData.cFileName)) + { + lpFindFileData.Path = Path.Combine(path, lpFindFileData.cFileName); + yield return lpFindFileData; + } + } + + FindClose(handle); + } + + private static bool IsValid(string cFileName) + { + if (cFileName.Equals(".", StringComparison.OrdinalIgnoreCase)) + { + return false; + } + if (cFileName.Equals("..", StringComparison.OrdinalIgnoreCase)) + { + return false; + } + + return true; + } + + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr FindFirstFile(string fileName, out WIN32_FIND_DATA data); + [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] + private static extern IntPtr FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA data); + [DllImport("kernel32")] private static extern bool FindClose(IntPtr hFindFile); - - } [StructLayout(LayoutKind.Sequential)] @@ -107,30 +163,8 @@ namespace MediaBrowser.Controller.IO highBits = highBits << 32; return DateTime.FromFileTime(highBits + (long)filetime.dwLowDateTime); } - } - public struct LazyFileInfo - { public string Path { get; set; } - - private WIN32_FIND_DATA? _FileInfo { get; set; } - - public WIN32_FIND_DATA FileInfo - { - get - { - if (_FileInfo == null) - { - _FileInfo = FileData.GetFileData(Path); - } - - return _FileInfo.Value; - } - set - { - _FileInfo = value; - } - } } } diff --git a/MediaBrowser.Controller/Kernel.cs b/MediaBrowser.Controller/Kernel.cs index fa2baafbcf..356e9e1e2f 100644 --- a/MediaBrowser.Controller/Kernel.cs +++ b/MediaBrowser.Controller/Kernel.cs @@ -69,7 +69,7 @@ namespace MediaBrowser.Controller public async override Task Init(IProgress progress) { ExtractFFMpeg(); - + await base.Init(progress).ConfigureAwait(false); progress.Report(new TaskProgress() { Description = "Loading Users", PercentComplete = 15 }); @@ -91,7 +91,7 @@ namespace MediaBrowser.Controller // Sort the providers by priority MetadataProviders = MetadataProviders.OrderBy(e => e.Priority); - + // Initialize the metadata providers Parallel.ForEach(MetadataProviders, provider => { @@ -106,7 +106,7 @@ namespace MediaBrowser.Controller /// void ItemController_PreBeginResolvePath(object sender, PreBeginResolveEventArgs e) { - if (e.File.FileInfo.IsHidden || e.File.FileInfo.IsSystemFile) + if (e.IsHidden || e.IsSystemFile) { // Ignore hidden files and folders e.Cancel = true; diff --git a/MediaBrowser.Controller/Library/ItemController.cs b/MediaBrowser.Controller/Library/ItemController.cs index f182f43f01..94fcf1f441 100644 --- a/MediaBrowser.Controller/Library/ItemController.cs +++ b/MediaBrowser.Controller/Library/ItemController.cs @@ -19,15 +19,8 @@ namespace MediaBrowser.Controller.Library /// This gives listeners a chance to cancel the operation and cause the path to be ignored. /// public event EventHandler PreBeginResolvePath; - private bool OnPreBeginResolvePath(Folder parent, string path, WIN32_FIND_DATA fileData) + private bool OnPreBeginResolvePath(PreBeginResolveEventArgs args) { - PreBeginResolveEventArgs args = new PreBeginResolveEventArgs() - { - Parent = parent, - File = new LazyFileInfo() { Path = path, FileInfo = fileData }, - Cancel = false - }; - if (PreBeginResolvePath != null) { PreBeginResolvePath(this, args); @@ -76,35 +69,35 @@ namespace MediaBrowser.Controller.Library /// public async Task GetItem(string path, Folder parent = null, WIN32_FIND_DATA? fileInfo = null) { - WIN32_FIND_DATA fileData = fileInfo ?? FileData.GetFileData(path); + ItemResolveEventArgs args = new ItemResolveEventArgs() + { + FileInfo = fileInfo ?? FileData.GetFileData(path), + Parent = parent, + Cancel = false, + Path = path + }; - if (!OnPreBeginResolvePath(parent, path, fileData)) + if (!OnPreBeginResolvePath(args)) { return null; } - LazyFileInfo[] fileSystemChildren; + WIN32_FIND_DATA[] fileSystemChildren; // Gather child folder and files - if (fileData.IsDirectory) + if (args.IsDirectory) { - fileSystemChildren = ConvertFileSystemEntries(Directory.GetFileSystemEntries(path, "*", SearchOption.TopDirectoryOnly)); + fileSystemChildren = FileData.GetFileSystemEntries(path, "*").ToArray(); bool isVirtualFolder = parent != null && parent.IsRoot; fileSystemChildren = FilterChildFileSystemEntries(fileSystemChildren, isVirtualFolder); } else { - fileSystemChildren = new LazyFileInfo[] { }; + fileSystemChildren = new WIN32_FIND_DATA[] { }; } - ItemResolveEventArgs args = new ItemResolveEventArgs() - { - File = new LazyFileInfo() { Path = path, FileInfo = fileData }, - FileSystemChildren = fileSystemChildren, - Parent = parent, - Cancel = false - }; + args.FileSystemChildren = fileSystemChildren; // Fire BeginResolvePath to see if anyone wants to cancel this operation if (!OnBeginResolvePath(args)) @@ -136,7 +129,7 @@ namespace MediaBrowser.Controller.Library /// /// Finds child BaseItems for a given Folder /// - private Task[] GetChildren(Folder folder, LazyFileInfo[] fileSystemChildren) + private Task[] GetChildren(Folder folder, WIN32_FIND_DATA[] fileSystemChildren) { Task[] tasks = new Task[fileSystemChildren.Length]; @@ -144,7 +137,7 @@ namespace MediaBrowser.Controller.Library { var child = fileSystemChildren[i]; - tasks[i] = GetItem(child.Path, folder, child.FileInfo); + tasks[i] = GetItem(child.Path, folder, child); } return tasks; @@ -153,14 +146,14 @@ namespace MediaBrowser.Controller.Library /// /// Transforms shortcuts into their actual paths /// - private LazyFileInfo[] FilterChildFileSystemEntries(LazyFileInfo[] fileSystemChildren, bool flattenShortcuts) + private WIN32_FIND_DATA[] FilterChildFileSystemEntries(WIN32_FIND_DATA[] fileSystemChildren, bool flattenShortcuts) { - LazyFileInfo[] returnArray = new LazyFileInfo[fileSystemChildren.Length]; - List resolvedShortcuts = new List(); + WIN32_FIND_DATA[] returnArray = new WIN32_FIND_DATA[fileSystemChildren.Length]; + List resolvedShortcuts = new List(); for (int i = 0; i < fileSystemChildren.Length; i++) { - LazyFileInfo file = fileSystemChildren[i]; + WIN32_FIND_DATA file = fileSystemChildren[i]; // If it's a shortcut, resolve it if (Shortcut.IsShortcut(file.Path)) @@ -176,18 +169,18 @@ namespace MediaBrowser.Controller.Library if (flattenShortcuts) { returnArray[i] = file; - LazyFileInfo[] newChildren = ConvertFileSystemEntries(Directory.GetFileSystemEntries(newPath, "*", SearchOption.TopDirectoryOnly)); + WIN32_FIND_DATA[] newChildren = FileData.GetFileSystemEntries(newPath, "*").ToArray(); resolvedShortcuts.AddRange(FilterChildFileSystemEntries(newChildren, false)); } else { - returnArray[i] = new LazyFileInfo() { Path = newPath, FileInfo = newPathData }; + returnArray[i] = newPathData; } } else { - returnArray[i] = new LazyFileInfo() { Path = newPath, FileInfo = newPathData }; + returnArray[i] = newPathData; } } else @@ -286,26 +279,12 @@ namespace MediaBrowser.Controller.Library item.DateModified = Directory.GetLastAccessTime(path); ItemResolveEventArgs args = new ItemResolveEventArgs(); - args.File = new LazyFileInfo() { Path = path }; - args.FileSystemChildren = ConvertFileSystemEntries(Directory.GetFileSystemEntries(path, "*", SearchOption.TopDirectoryOnly)); + args.FileInfo = FileData.GetFileData(path); + args.FileSystemChildren = FileData.GetFileSystemEntries(path, "*").ToArray(); await Kernel.Instance.ExecuteMetadataProviders(item, args).ConfigureAwait(false); return item; } - - private LazyFileInfo[] ConvertFileSystemEntries(string[] files) - { - LazyFileInfo[] items = new LazyFileInfo[files.Length]; - - for (int i = 0; i < files.Length; i++) - { - string file = files[i]; - - items[i] = new LazyFileInfo() { Path = file }; - } - - return items; - } } } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index a4b7dbc765..41bd42040e 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -30,6 +30,10 @@ 4 + + False + ..\packages\protobuf-net.2.0.0.480\lib\net40\protobuf-net.dll + diff --git a/MediaBrowser.Controller/Providers/FolderProviderFromXml.cs b/MediaBrowser.Controller/Providers/FolderProviderFromXml.cs index 2249fb6a50..f0c95e4f78 100644 --- a/MediaBrowser.Controller/Providers/FolderProviderFromXml.cs +++ b/MediaBrowser.Controller/Providers/FolderProviderFromXml.cs @@ -1,4 +1,5 @@ using System.ComponentModel.Composition; +using System.IO; using System.Threading.Tasks; using MediaBrowser.Controller.Events; using MediaBrowser.Controller.Xml; @@ -21,11 +22,9 @@ namespace MediaBrowser.Controller.Providers public override Task FetchAsync(BaseEntity item, ItemResolveEventArgs args) { - var metadataFile = args.GetFileSystemEntryByName("folder.xml"); - - if (metadataFile.HasValue) + if (args.ContainsFile("folder.xml")) { - return Task.Run(() => { new FolderXmlParser().Fetch(item as Folder, metadataFile.Value.Path); }); + return Task.Run(() => { new FolderXmlParser().Fetch(item as Folder, Path.Combine(args.Path, "folder.xml")); }); } return Task.FromResult(null); diff --git a/MediaBrowser.Controller/Providers/LocalTrailerProvider.cs b/MediaBrowser.Controller/Providers/LocalTrailerProvider.cs index 18ca261dca..536294c7b2 100644 --- a/MediaBrowser.Controller/Providers/LocalTrailerProvider.cs +++ b/MediaBrowser.Controller/Providers/LocalTrailerProvider.cs @@ -3,6 +3,7 @@ using System.ComponentModel.Composition; using System.IO; using System.Threading.Tasks; using MediaBrowser.Controller.Events; +using MediaBrowser.Controller.IO; using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Providers @@ -22,27 +23,21 @@ namespace MediaBrowser.Controller.Providers public async override Task FetchAsync(BaseEntity item, ItemResolveEventArgs args) { - var trailerPath = args.GetFileSystemEntryByName("trailers", true); - - if (trailerPath.HasValue) + if (args.ContainsFolder("trailers")) { - string[] allFiles = Directory.GetFileSystemEntries(trailerPath.Value.Path, "*", SearchOption.TopDirectoryOnly); - - List