From 95341c5c96059e4bd70f290ff05ae3abc9c49257 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sat, 12 Nov 2016 23:33:51 -0500 Subject: [PATCH 01/15] update .net core startup --- .../IO/ManagedFileSystem.cs | 5 +- .../IO/WindowsFileSystem.cs | 13 - Emby.Server.Core/ApplicationHost.cs | 114 ++++----- Emby.Server.Core/INativeApp.cs | 78 ------ .../MediaBrowser.Server.Mono.csproj | 2 +- MediaBrowser.Server.Mono/MonoAppHost.cs | 139 +++++++++++ MediaBrowser.Server.Mono/Native/MonoApp.cs | 164 ------------- .../Native/MonoFileSystem.cs | 2 +- MediaBrowser.Server.Mono/Program.cs | 5 +- MediaBrowser.ServerApplication/MainStartup.cs | 38 ++- .../MediaBrowser.ServerApplication.csproj | 2 +- .../WindowsApp.cs => WindowsAppHost.cs} | 231 ++++++++---------- src/Emby.Server/ApplicationPathHelper.cs | 47 ++++ src/Emby.Server/CoreAppHost.cs | 107 ++++++++ src/Emby.Server/CoreSystemEvents.cs | 11 + src/Emby.Server/Data/DbConnector.cs | 52 ++++ src/Emby.Server/IO/MemoryStreamFactory.cs | 33 +++ src/Emby.Server/PowerManagement.cs | 15 ++ src/Emby.Server/Program.cs | 170 ++----------- src/Emby.Server/project.json | 6 +- 20 files changed, 602 insertions(+), 632 deletions(-) delete mode 100644 Emby.Common.Implementations/IO/WindowsFileSystem.cs delete mode 100644 Emby.Server.Core/INativeApp.cs create mode 100644 MediaBrowser.Server.Mono/MonoAppHost.cs delete mode 100644 MediaBrowser.Server.Mono/Native/MonoApp.cs rename MediaBrowser.ServerApplication/{Native/WindowsApp.cs => WindowsAppHost.cs} (62%) create mode 100644 src/Emby.Server/ApplicationPathHelper.cs create mode 100644 src/Emby.Server/CoreAppHost.cs create mode 100644 src/Emby.Server/CoreSystemEvents.cs create mode 100644 src/Emby.Server/Data/DbConnector.cs create mode 100644 src/Emby.Server/IO/MemoryStreamFactory.cs create mode 100644 src/Emby.Server/PowerManagement.cs diff --git a/Emby.Common.Implementations/IO/ManagedFileSystem.cs b/Emby.Common.Implementations/IO/ManagedFileSystem.cs index 81ca8dcff..1f0aa55fa 100644 --- a/Emby.Common.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Common.Implementations/IO/ManagedFileSystem.cs @@ -18,12 +18,13 @@ namespace Emby.Common.Implementations.IO private readonly bool _supportsAsyncFileStreams; private char[] _invalidFileNameChars; private readonly List _shortcutHandlers = new List(); - protected bool EnableFileSystemRequestConcat = true; + private bool EnableFileSystemRequestConcat = true; - public ManagedFileSystem(ILogger logger, bool supportsAsyncFileStreams, bool enableManagedInvalidFileNameChars) + public ManagedFileSystem(ILogger logger, bool supportsAsyncFileStreams, bool enableManagedInvalidFileNameChars, bool enableFileSystemRequestConcat) { Logger = logger; _supportsAsyncFileStreams = supportsAsyncFileStreams; + EnableFileSystemRequestConcat = enableFileSystemRequestConcat; SetInvalidFileNameChars(enableManagedInvalidFileNameChars); } diff --git a/Emby.Common.Implementations/IO/WindowsFileSystem.cs b/Emby.Common.Implementations/IO/WindowsFileSystem.cs deleted file mode 100644 index 3eafeb2f7..000000000 --- a/Emby.Common.Implementations/IO/WindowsFileSystem.cs +++ /dev/null @@ -1,13 +0,0 @@ -using MediaBrowser.Model.Logging; - -namespace Emby.Common.Implementations.IO -{ - public class WindowsFileSystem : ManagedFileSystem - { - public WindowsFileSystem(ILogger logger) - : base(logger, true, true) - { - EnableFileSystemRequestConcat = false; - } - } -} diff --git a/Emby.Server.Core/ApplicationHost.cs b/Emby.Server.Core/ApplicationHost.cs index 5c8aea7ed..7f795a68d 100644 --- a/Emby.Server.Core/ApplicationHost.cs +++ b/Emby.Server.Core/ApplicationHost.cs @@ -142,7 +142,7 @@ namespace Emby.Server.Core /// /// Class CompositionRoot /// - public class ApplicationHost : BaseApplicationHost, IServerApplicationHost, IDependencyContainer + public abstract class ApplicationHost : BaseApplicationHost, IServerApplicationHost, IDependencyContainer { /// /// Gets the server configuration manager. @@ -257,11 +257,9 @@ namespace Emby.Server.Core protected IAuthService AuthService { get; private set; } - private readonly StartupOptions _startupOptions; + protected readonly StartupOptions StartupOptions; private readonly string _releaseAssetFilename; - internal INativeApp NativeApp { get; set; } - internal IPowerManagement PowerManagement { get; private set; } internal IImageEncoder ImageEncoder { get; private set; } @@ -275,7 +273,6 @@ namespace Emby.Server.Core ILogManager logManager, StartupOptions options, IFileSystem fileSystem, - INativeApp nativeApp, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, @@ -293,11 +290,10 @@ namespace Emby.Server.Core memoryStreamFactory, networkManager) { - _startupOptions = options; + StartupOptions = options; _certificateGenerator = certificateGenerator; _releaseAssetFilename = releaseAssetFilename; _defaultUserNameFactory = defaultUsernameFactory; - NativeApp = nativeApp; PowerManagement = powerManagement; ImageEncoder = imageEncoder; @@ -314,19 +310,11 @@ namespace Emby.Server.Core { get { - return _version ?? (_version = GetAssembly(NativeApp.GetType()).GetName().Version); + return _version ?? (_version = GetAssembly(GetType()).GetName().Version); } } - public override bool IsRunningAsService - { - get { return NativeApp.IsRunningAsService; } - } - - public bool SupportsRunningAsService - { - get { return NativeApp.SupportsRunningAsService; } - } + public abstract bool SupportsRunningAsService { get; } /// /// Gets the name. @@ -345,19 +333,7 @@ namespace Emby.Server.Core return type.GetTypeInfo().Assembly; } - /// - /// Gets a value indicating whether this instance can self restart. - /// - /// true if this instance can self restart; otherwise, false. - public override bool CanSelfRestart - { - get { return NativeApp.CanSelfRestart; } - } - - public bool SupportsAutoRunAtStartup - { - get { return NativeApp.SupportsAutoRunAtStartup; } - } + public abstract bool SupportsAutoRunAtStartup { get; } private void SetBaseExceptionMessage() { @@ -580,11 +556,11 @@ namespace Emby.Server.Core UserRepository = await GetUserRepository().ConfigureAwait(false); - var displayPreferencesRepo = new SqliteDisplayPreferencesRepository(LogManager, JsonSerializer, ApplicationPaths, NativeApp.GetDbConnector(), MemoryStreamFactory); + var displayPreferencesRepo = new SqliteDisplayPreferencesRepository(LogManager, JsonSerializer, ApplicationPaths, GetDbConnector(), MemoryStreamFactory); DisplayPreferencesRepository = displayPreferencesRepo; RegisterSingleInstance(DisplayPreferencesRepository); - var itemRepo = new SqliteItemRepository(ServerConfigurationManager, JsonSerializer, LogManager, NativeApp.GetDbConnector(), MemoryStreamFactory); + var itemRepo = new SqliteItemRepository(ServerConfigurationManager, JsonSerializer, LogManager, GetDbConnector(), MemoryStreamFactory); ItemRepository = itemRepo; RegisterSingleInstance(ItemRepository); @@ -707,7 +683,7 @@ namespace Emby.Server.Core EncodingManager = new EncodingManager(FileSystemManager, Logger, MediaEncoder, ChapterManager, LibraryManager); RegisterSingleInstance(EncodingManager); - var sharingRepo = new SharingRepository(LogManager, ApplicationPaths, NativeApp.GetDbConnector()); + var sharingRepo = new SharingRepository(LogManager, ApplicationPaths, GetDbConnector()); await sharingRepo.Initialize().ConfigureAwait(false); RegisterSingleInstance(new SharingManager(sharingRepo, ServerConfigurationManager, LibraryManager, this)); @@ -727,7 +703,7 @@ namespace Emby.Server.Core await displayPreferencesRepo.Initialize().ConfigureAwait(false); - var userDataRepo = new SqliteUserDataRepository(LogManager, ApplicationPaths, NativeApp.GetDbConnector()); + var userDataRepo = new SqliteUserDataRepository(LogManager, ApplicationPaths, GetDbConnector()); ((UserDataManager)UserDataManager).Repository = userDataRepo; await itemRepo.Initialize(userDataRepo).ConfigureAwait(false); @@ -770,14 +746,16 @@ namespace Emby.Server.Core { var maxConcurrentImageProcesses = Math.Max(Environment.ProcessorCount, 4); - if (_startupOptions.ContainsOption("-imagethreads")) + if (StartupOptions.ContainsOption("-imagethreads")) { - int.TryParse(_startupOptions.GetOption("-imagethreads"), NumberStyles.Any, CultureInfo.InvariantCulture, out maxConcurrentImageProcesses); + int.TryParse(StartupOptions.GetOption("-imagethreads"), NumberStyles.Any, CultureInfo.InvariantCulture, out maxConcurrentImageProcesses); } return new ImageProcessor(LogManager.GetLogger("ImageProcessor"), ServerConfigurationManager.ApplicationPaths, FileSystemManager, JsonSerializer, ImageEncoder, maxConcurrentImageProcesses, () => LibraryManager, TimerFactory); } + protected abstract FFMpegInstallInfo GetFfmpegInstallInfo(); + /// /// Registers the media encoder. /// @@ -787,8 +765,8 @@ namespace Emby.Server.Core string encoderPath = null; string probePath = null; - var info = await new FFMpegLoader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager, NativeApp.GetFfmpegInstallInfo()) - .GetFFMpegInfo(_startupOptions, progress).ConfigureAwait(false); + var info = await new FFMpegLoader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager, GetFfmpegInstallInfo()) + .GetFFMpegInfo(StartupOptions, progress).ConfigureAwait(false); encoderPath = info.EncoderPath; probePath = info.ProbePath; @@ -825,7 +803,7 @@ namespace Emby.Server.Core /// Task{IUserRepository}. private async Task GetUserRepository() { - var repo = new SqliteUserRepository(LogManager, ApplicationPaths, JsonSerializer, NativeApp.GetDbConnector(), MemoryStreamFactory); + var repo = new SqliteUserRepository(LogManager, ApplicationPaths, JsonSerializer, GetDbConnector(), MemoryStreamFactory); await repo.Initialize().ConfigureAwait(false); @@ -838,7 +816,7 @@ namespace Emby.Server.Core /// Task{IUserRepository}. private async Task GetFileOrganizationRepository() { - var repo = new SqliteFileOrganizationRepository(LogManager, ServerConfigurationManager.ApplicationPaths, NativeApp.GetDbConnector()); + var repo = new SqliteFileOrganizationRepository(LogManager, ServerConfigurationManager.ApplicationPaths, GetDbConnector()); await repo.Initialize().ConfigureAwait(false); @@ -847,7 +825,7 @@ namespace Emby.Server.Core private async Task GetAuthenticationRepository() { - var repo = new AuthenticationRepository(LogManager, ServerConfigurationManager.ApplicationPaths, NativeApp.GetDbConnector()); + var repo = new AuthenticationRepository(LogManager, ServerConfigurationManager.ApplicationPaths, GetDbConnector()); await repo.Initialize().ConfigureAwait(false); @@ -856,7 +834,7 @@ namespace Emby.Server.Core private async Task GetActivityLogRepository() { - var repo = new ActivityRepository(LogManager, ServerConfigurationManager.ApplicationPaths, NativeApp.GetDbConnector()); + var repo = new ActivityRepository(LogManager, ServerConfigurationManager.ApplicationPaths, GetDbConnector()); await repo.Initialize().ConfigureAwait(false); @@ -865,7 +843,7 @@ namespace Emby.Server.Core private async Task GetSyncRepository() { - var repo = new SyncRepository(LogManager, JsonSerializer, ServerConfigurationManager.ApplicationPaths, NativeApp.GetDbConnector()); + var repo = new SyncRepository(LogManager, JsonSerializer, ServerConfigurationManager.ApplicationPaths, GetDbConnector()); await repo.Initialize().ConfigureAwait(false); @@ -877,7 +855,7 @@ namespace Emby.Server.Core /// private async Task ConfigureNotificationsRepository() { - var repo = new SqliteNotificationsRepository(LogManager, ApplicationPaths, NativeApp.GetDbConnector()); + var repo = new SqliteNotificationsRepository(LogManager, ApplicationPaths, GetDbConnector()); await repo.Initialize().ConfigureAwait(false); @@ -1123,24 +1101,12 @@ namespace Emby.Server.Core Logger.ErrorException("Error sending server restart notification", ex); } - Logger.Info("Calling NativeApp.Restart"); + Logger.Info("Calling RestartInternal"); - NativeApp.Restart(_startupOptions); + RestartInternal(); } - /// - /// Gets or sets a value indicating whether this instance can self update. - /// - /// true if this instance can self update; otherwise, false. - public override bool CanSelfUpdate - { - get - { -#pragma warning disable 162 - return NativeApp.CanSelfUpdate; -#pragma warning restore 162 - } - } + protected abstract void RestartInternal(); /// /// Gets the composable part assemblies. @@ -1196,14 +1162,16 @@ namespace Emby.Server.Core // Xbmc list.Add(GetAssembly(typeof(ArtistNfoProvider))); - list.AddRange(NativeApp.GetAssembliesWithParts()); + list.AddRange(GetAssembliesWithPartsInternal()); // Include composable parts in the running assembly - list.Add(GetAssembly(GetType())); + list.Add(GetAssembly(typeof(ApplicationHost))); return list; } + protected abstract List GetAssembliesWithPartsInternal(); + /// /// Gets the plugin assemblies. /// @@ -1280,7 +1248,7 @@ namespace Emby.Server.Core EncoderLocationType = MediaEncoder.EncoderLocationType, SystemArchitecture = EnvironmentInfo.SystemArchitecture, SystemUpdateLevel = ConfigurationManager.CommonConfiguration.SystemUpdateLevel, - PackageName = _startupOptions.GetOption("-package") + PackageName = StartupOptions.GetOption("-package") }; } @@ -1456,9 +1424,11 @@ namespace Emby.Server.Core Logger.ErrorException("Error sending server shutdown notification", ex); } - NativeApp.Shutdown(); + ShutdownInternal(); } + protected abstract void ShutdownInternal(); + /// /// Registers the server with administrator access. /// @@ -1468,7 +1438,7 @@ namespace Emby.Server.Core try { - NativeApp.AuthorizeServer( + AuthorizeServer( UdpServerEntryPoint.PortNumber, ServerConfigurationManager.Configuration.HttpServerPortNumber, ServerConfigurationManager.Configuration.HttpsPortNumber, @@ -1481,6 +1451,9 @@ namespace Emby.Server.Core } } + protected abstract void AuthorizeServer(int udpPort, int httpServerPort, int httpsServerPort, string applicationPath, string tempDirectory); + protected abstract IDbConnector GetDbConnector(); + public event EventHandler HasUpdateAvailableChanged; private bool _hasUpdateAvailable; @@ -1551,10 +1524,12 @@ namespace Emby.Server.Core { if (SupportsAutoRunAtStartup) { - NativeApp.ConfigureAutoRun(autorun); + ConfigureAutoRunInternal(autorun); } } + protected abstract void ConfigureAutoRunInternal(bool autorun); + /// /// This returns localhost in the case of no external dns, and the hostname if the /// dns is prefixed with a valid Uri prefix. @@ -1578,16 +1553,15 @@ namespace Emby.Server.Core } } - public void LaunchUrl(string url) - { - NativeApp.LaunchUrl(url); - } + public abstract void LaunchUrl(string url); public void EnableLoopback(string appName) { - NativeApp.EnableLoopback(appName); + EnableLoopbackInternal(appName); } + protected abstract void EnableLoopbackInternal(string appName); + private void RegisterModules() { var moduleTypes = GetExportTypes(); diff --git a/Emby.Server.Core/INativeApp.cs b/Emby.Server.Core/INativeApp.cs deleted file mode 100644 index a4e4b3221..000000000 --- a/Emby.Server.Core/INativeApp.cs +++ /dev/null @@ -1,78 +0,0 @@ -using MediaBrowser.Common.Net; -using MediaBrowser.Model.Logging; -using System.Collections.Generic; -using System.Reflection; -using Emby.Server.Core; -using Emby.Server.Core.Data; -using Emby.Server.Core.FFMpeg; - -namespace Emby.Server.Core -{ - public interface INativeApp - { - /// - /// Gets the assemblies with parts. - /// - /// List<Assembly>. - List GetAssembliesWithParts(); - - /// - /// Authorizes the server. - /// - void AuthorizeServer(int udpPort, int httpServerPort, int httpsServerPort, string applicationPath, string tempDirectory); - - /// - /// Gets a value indicating whether [supports running as service]. - /// - /// true if [supports running as service]; otherwise, false. - bool SupportsRunningAsService { get; } - - /// - /// Gets a value indicating whether this instance is running as service. - /// - /// true if this instance is running as service; otherwise, false. - bool IsRunningAsService { get; } - - /// - /// Gets a value indicating whether this instance can self restart. - /// - /// true if this instance can self restart; otherwise, false. - bool CanSelfRestart { get; } - - /// - /// Gets a value indicating whether [supports autorun at startup]. - /// - /// true if [supports autorun at startup]; otherwise, false. - bool SupportsAutoRunAtStartup { get; } - - /// - /// Gets a value indicating whether this instance can self update. - /// - /// true if this instance can self update; otherwise, false. - bool CanSelfUpdate { get; } - - /// - /// Shutdowns this instance. - /// - void Shutdown(); - - /// - /// Restarts this instance. - /// - void Restart(StartupOptions startupOptions); - - /// - /// Configures the automatic run. - /// - /// if set to true [autorun]. - void ConfigureAutoRun(bool autorun); - - FFMpegInstallInfo GetFfmpegInstallInfo(); - - void LaunchUrl(string url); - - IDbConnector GetDbConnector(); - - void EnableLoopback(string appName); - } -} diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj index ca830b2f4..270c43e13 100644 --- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj +++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj @@ -106,7 +106,7 @@ Properties\SharedVersion.cs - + diff --git a/MediaBrowser.Server.Mono/MonoAppHost.cs b/MediaBrowser.Server.Mono/MonoAppHost.cs new file mode 100644 index 000000000..5f0ecde24 --- /dev/null +++ b/MediaBrowser.Server.Mono/MonoAppHost.cs @@ -0,0 +1,139 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using Emby.Server.Core; +using Emby.Server.Core.Data; +using Emby.Server.Core.FFMpeg; +using MediaBrowser.IsoMounter; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.System; +using MediaBrowser.Server.Mono.Native; + +namespace MediaBrowser.Server.Mono +{ + public class MonoAppHost : ApplicationHost + { + public MonoAppHost(ServerApplicationPaths applicationPaths, ILogManager logManager, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, IMemoryStreamFactory memoryStreamFactory, MediaBrowser.Common.Net.INetworkManager networkManager, Action certificateGenerator, Func defaultUsernameFactory) : base(applicationPaths, logManager, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, memoryStreamFactory, networkManager, certificateGenerator, defaultUsernameFactory) + { + } + + public override bool CanSelfRestart + { + get + { + // A restart script must be provided + return StartupOptions.ContainsOption("-restartpath"); + } + } + + public override bool CanSelfUpdate + { + get + { + return false; + } + } + + protected override FFMpegInstallInfo GetFfmpegInstallInfo() + { + var info = new FFMpegInstallInfo(); + + // Windows builds: http://ffmpeg.zeranoe.com/builds/ + // Linux builds: http://johnvansickle.com/ffmpeg/ + // OS X builds: http://ffmpegmac.net/ + // OS X x64: http://www.evermeet.cx/ffmpeg/ + + var environment = (MonoEnvironmentInfo) EnvironmentInfo; + + if (environment.IsBsd) + { + + } + else if (environment.OperatingSystem == Model.System.OperatingSystem.Linux) + { + info.ArchiveType = "7z"; + info.Version = "20160215"; + } + + // No version available - user requirement + info.DownloadUrls = new string[] { }; + + return info; + } + + protected override void RestartInternal() + { + MainClass.Restart(StartupOptions); + } + + protected override List GetAssembliesWithPartsInternal() + { + var list = new List(); + + list.Add(GetType().Assembly); + list.AddRange(GetLinuxAssemblies()); + + return list; + } + + private IEnumerable GetLinuxAssemblies() + { + var list = new List(); + + list.Add(typeof(LinuxIsoManager).Assembly); + + return list; + } + + protected override void ShutdownInternal() + { + MainClass.Shutdown(); + } + + protected override void AuthorizeServer(int udpPort, int httpServerPort, int httpsServerPort, string applicationPath, string tempDirectory) + { + throw new NotImplementedException(); + } + + protected override IDbConnector GetDbConnector() + { + return new DbConnector(Logger); + } + + protected override void ConfigureAutoRunInternal(bool autorun) + { + throw new NotImplementedException(); + } + + public override void LaunchUrl(string url) + { + throw new NotImplementedException(); + } + + protected override void EnableLoopbackInternal(string appName) + { + } + + public override bool SupportsRunningAsService + { + get + { + return false; + } + } + + public override bool SupportsAutoRunAtStartup + { + get { return false; } + } + + public override bool IsRunningAsService + { + get + { + return false; + } + } + } +} diff --git a/MediaBrowser.Server.Mono/Native/MonoApp.cs b/MediaBrowser.Server.Mono/Native/MonoApp.cs deleted file mode 100644 index 8257a1b8d..000000000 --- a/MediaBrowser.Server.Mono/Native/MonoApp.cs +++ /dev/null @@ -1,164 +0,0 @@ -using MediaBrowser.Common.Net; -using MediaBrowser.IsoMounter; -using MediaBrowser.Model.Logging; -using MediaBrowser.Server.Startup.Common; -using Mono.Unix.Native; -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text.RegularExpressions; -using Emby.Common.Implementations.Networking; -using Emby.Server.Core; -using Emby.Server.Core.Data; -using Emby.Server.Core.FFMpeg; -using MediaBrowser.Model.System; - -namespace MediaBrowser.Server.Mono.Native -{ - public class MonoApp : INativeApp - { - protected StartupOptions StartupOptions { get; private set; } - protected ILogger Logger { get; private set; } - private readonly MonoEnvironmentInfo _environment; - - public MonoApp(StartupOptions startupOptions, ILogger logger, MonoEnvironmentInfo environment) - { - StartupOptions = startupOptions; - Logger = logger; - _environment = environment; - } - - /// - /// Shutdowns this instance. - /// - public void Shutdown() - { - MainClass.Shutdown(); - } - - /// - /// Determines whether this instance [can self restart]. - /// - /// true if this instance can self restart; otherwise, false. - public bool CanSelfRestart - { - get - { - // A restart script must be provided - return StartupOptions.ContainsOption("-restartpath"); - } - } - - /// - /// Restarts this instance. - /// - public void Restart(StartupOptions startupOptions) - { - MainClass.Restart(startupOptions); - } - - /// - /// Gets a value indicating whether this instance can self update. - /// - /// true if this instance can self update; otherwise, false. - public bool CanSelfUpdate - { - get - { - return false; - } - } - - public bool SupportsAutoRunAtStartup - { - get { return false; } - } - - public List GetAssembliesWithParts() - { - var list = new List(); - - list.Add(GetType().Assembly); - - return list; - } - - private IEnumerable GetLinuxAssemblies() - { - var list = new List(); - - //list.Add(typeof(LinuxIsoManager).Assembly); - - return list; - } - - public void AuthorizeServer(int udpPort, int httpServerPort, int httpsPort, string applicationPath, string tempDirectory) - { - } - - public bool SupportsRunningAsService - { - get - { - return false; - } - } - - public bool IsRunningAsService - { - get - { - return false; - } - } - - public void ConfigureAutoRun(bool autorun) - { - } - - public INetworkManager CreateNetworkManager(ILogger logger) - { - return new NetworkManager(logger); - } - - public FFMpegInstallInfo GetFfmpegInstallInfo() - { - var info = new FFMpegInstallInfo(); - - // Windows builds: http://ffmpeg.zeranoe.com/builds/ - // Linux builds: http://johnvansickle.com/ffmpeg/ - // OS X builds: http://ffmpegmac.net/ - // OS X x64: http://www.evermeet.cx/ffmpeg/ - - if (_environment.IsBsd) - { - - } - else if (_environment.OperatingSystem == Model.System.OperatingSystem.Linux) - { - info.ArchiveType = "7z"; - info.Version = "20160215"; - } - - // No version available - user requirement - info.DownloadUrls = new string[] { }; - - return info; - } - - public void LaunchUrl(string url) - { - throw new NotImplementedException(); - } - - public IDbConnector GetDbConnector() - { - return new DbConnector(Logger); - } - - public void EnableLoopback(string appName) - { - - } - } -} diff --git a/MediaBrowser.Server.Mono/Native/MonoFileSystem.cs b/MediaBrowser.Server.Mono/Native/MonoFileSystem.cs index 963956694..748b94604 100644 --- a/MediaBrowser.Server.Mono/Native/MonoFileSystem.cs +++ b/MediaBrowser.Server.Mono/Native/MonoFileSystem.cs @@ -6,7 +6,7 @@ namespace MediaBrowser.Server.Mono.Native { public class MonoFileSystem : ManagedFileSystem { - public MonoFileSystem(ILogger logger, bool supportsAsyncFileStreams, bool enableManagedInvalidFileNameChars) : base(logger, supportsAsyncFileStreams, enableManagedInvalidFileNameChars) + public MonoFileSystem(ILogger logger, bool supportsAsyncFileStreams, bool enableManagedInvalidFileNameChars) : base(logger, supportsAsyncFileStreams, enableManagedInvalidFileNameChars, false) { } diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs index 9a8ac7763..48390f078 100644 --- a/MediaBrowser.Server.Mono/Program.cs +++ b/MediaBrowser.Server.Mono/Program.cs @@ -91,15 +91,12 @@ namespace MediaBrowser.Server.Mono var environmentInfo = GetEnvironmentInfo(); - var nativeApp = new MonoApp(options, logManager.GetLogger("App"), environmentInfo); - var imageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, logManager, fileSystem, options, () => _appHost.HttpClient, appPaths); - _appHost = new ApplicationHost(appPaths, + _appHost = new MonoAppHost(appPaths, logManager, options, fileSystem, - nativeApp, new PowerManagement(), "emby.mono.zip", environmentInfo, diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index fa8cccf34..ab0a36aff 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -37,7 +37,7 @@ namespace MediaBrowser.ServerApplication private static ILogger _logger; - private static bool _isRunningAsService = false; + public static bool IsRunningAsService = false; private static bool _canRestartService = false; private static bool _appHostDisposed; @@ -72,9 +72,9 @@ namespace MediaBrowser.ServerApplication public static void Main() { var options = new StartupOptions(); - _isRunningAsService = options.ContainsOption("-service"); + IsRunningAsService = options.ContainsOption("-service"); - if (_isRunningAsService) + if (IsRunningAsService) { //_canRestartService = CanRestartWindowsService(); } @@ -88,7 +88,7 @@ namespace MediaBrowser.ServerApplication var success = SetDllDirectory(architecturePath); - var appPaths = CreateApplicationPaths(applicationPath, _isRunningAsService); + var appPaths = CreateApplicationPaths(applicationPath, IsRunningAsService); var logManager = new NlogManager(appPaths.LogDirectoryPath, "server"); logManager.ReloadLogger(LogSeverity.Debug); @@ -148,7 +148,7 @@ namespace MediaBrowser.ServerApplication try { - RunApplication(appPaths, logManager, _isRunningAsService, options); + RunApplication(appPaths, logManager, IsRunningAsService, options); } finally { @@ -204,7 +204,7 @@ namespace MediaBrowser.ServerApplication } } - if (!_isRunningAsService) + if (!IsRunningAsService) { return IsAlreadyRunningAsService(applicationPath); } @@ -272,7 +272,7 @@ namespace MediaBrowser.ServerApplication { get { - if (_isRunningAsService) + if (IsRunningAsService) { return _canRestartService; } @@ -295,7 +295,7 @@ namespace MediaBrowser.ServerApplication return false; #endif - if (_isRunningAsService) + if (IsRunningAsService) { return _canRestartService; } @@ -317,22 +317,16 @@ namespace MediaBrowser.ServerApplication /// The options. private static void RunApplication(ServerApplicationPaths appPaths, ILogManager logManager, bool runService, StartupOptions options) { - var fileSystem = new WindowsFileSystem(logManager.GetLogger("FileSystem")); + var fileSystem = new ManagedFileSystem(logManager.GetLogger("FileSystem"), true, true, true); fileSystem.AddShortcutHandler(new LnkShortcutHandler()); fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem)); - var nativeApp = new WindowsApp(fileSystem, _logger) - { - IsRunningAsService = runService - }; - var imageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, logManager, fileSystem, options, () => _appHost.HttpClient, appPaths); - _appHost = new ApplicationHost(appPaths, + _appHost = new WindowsAppHost(appPaths, logManager, options, fileSystem, - nativeApp, new PowerManagement(), "emby.windows.zip", new EnvironmentInfo(), @@ -440,7 +434,7 @@ namespace MediaBrowser.ServerApplication public static void Invoke(Action action) { - if (_isRunningAsService) + if (IsRunningAsService) { action(); } @@ -578,7 +572,7 @@ namespace MediaBrowser.ServerApplication /// The instance containing the event data. static void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e) { - if (e.Reason == SessionEndReasons.SystemShutdown || !_isRunningAsService) + if (e.Reason == SessionEndReasons.SystemShutdown || !IsRunningAsService) { Shutdown(); } @@ -595,7 +589,7 @@ namespace MediaBrowser.ServerApplication new UnhandledExceptionWriter(_appHost.ServerConfigurationManager.ApplicationPaths, _logger, _appHost.LogManager).Log(exception); - if (!_isRunningAsService) + if (!IsRunningAsService) { MessageBox.Show("Unhandled exception: " + exception.Message); } @@ -623,7 +617,7 @@ namespace MediaBrowser.ServerApplication // Update is there - execute update try { - var serviceName = _isRunningAsService ? BackgroundService.GetExistingServiceName() : string.Empty; + var serviceName = IsRunningAsService ? BackgroundService.GetExistingServiceName() : string.Empty; new ApplicationUpdater().UpdateApplication(appPaths, updateArchive, logger, serviceName); // And just let the app exit so it can update @@ -642,7 +636,7 @@ namespace MediaBrowser.ServerApplication public static void Shutdown() { - if (_isRunningAsService) + if (IsRunningAsService) { ShutdownWindowsService(); } @@ -658,7 +652,7 @@ namespace MediaBrowser.ServerApplication { DisposeAppHost(); - if (_isRunningAsService) + if (IsRunningAsService) { RestartWindowsService(); } diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index f6aef5744..6984ff2be 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -138,7 +138,6 @@ - @@ -156,6 +155,7 @@ SplashForm.cs + diff --git a/MediaBrowser.ServerApplication/Native/WindowsApp.cs b/MediaBrowser.ServerApplication/WindowsAppHost.cs similarity index 62% rename from MediaBrowser.ServerApplication/Native/WindowsApp.cs rename to MediaBrowser.ServerApplication/WindowsAppHost.cs index babe952d6..8fd718432 100644 --- a/MediaBrowser.ServerApplication/Native/WindowsApp.cs +++ b/MediaBrowser.ServerApplication/WindowsAppHost.cs @@ -1,131 +1,31 @@ using System; -using MediaBrowser.Common.Net; -using MediaBrowser.Model.Logging; -using MediaBrowser.Server.Startup.Common; -using MediaBrowser.ServerApplication.Networking; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; -using System.Windows.Forms; using Emby.Server.Core; using Emby.Server.Core.Data; using Emby.Server.Core.FFMpeg; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.IO; using MediaBrowser.Model.IO; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.System; +using MediaBrowser.ServerApplication.Native; -namespace MediaBrowser.ServerApplication.Native +namespace MediaBrowser.ServerApplication { - public class WindowsApp : INativeApp + public class WindowsAppHost : ApplicationHost { - private readonly IFileSystem _fileSystem; - private readonly ILogger _logger; - - public WindowsApp(IFileSystem fileSystem, ILogger logger) + public WindowsAppHost(ServerApplicationPaths applicationPaths, ILogManager logManager, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, IMemoryStreamFactory memoryStreamFactory, MediaBrowser.Common.Net.INetworkManager networkManager, Action certificateGenerator, Func defaultUsernameFactory) + : base(applicationPaths, logManager, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, memoryStreamFactory, networkManager, certificateGenerator, defaultUsernameFactory) { - _fileSystem = fileSystem; - _logger = logger; } - public List GetAssembliesWithParts() + public override bool IsRunningAsService { - var list = new List(); - - if (!System.Environment.Is64BitProcess) - { - //list.Add(typeof(PismoIsoManager).Assembly); - } - - list.Add(GetType().Assembly); - - return list; + get { return MainStartup.IsRunningAsService; } } - public void AuthorizeServer(int udpPort, int httpServerPort, int httpsPort, string applicationPath, string tempDirectory) - { - ServerAuthorization.AuthorizeServer(udpPort, httpServerPort, httpsPort, applicationPath, tempDirectory); - } - - public bool SupportsLibraryMonitor - { - get { return true; } - } - - public bool SupportsRunningAsService - { - get - { - return true; - } - } - - public bool IsRunningAsService - { - get; - set; - } - - public bool CanSelfRestart - { - get - { - return MainStartup.CanSelfRestart; - } - } - - public bool SupportsAutoRunAtStartup - { - get - { - return true; - } - } - - public bool CanSelfUpdate - { - get - { - return MainStartup.CanSelfUpdate; - } - } - - public void Shutdown() - { - MainStartup.Shutdown(); - } - - public void Restart(StartupOptions startupOptions) - { - MainStartup.Restart(); - } - - public void ConfigureAutoRun(bool autorun) - { - var shortcutPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.StartMenu), "Emby", "Emby Server.lnk"); - - var startupPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Startup); - - if (autorun) - { - //Copy our shortut into the startup folder for this user - var targetPath = Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "Emby Server.lnk"); - _fileSystem.CreateDirectory(Path.GetDirectoryName(targetPath)); - File.Copy(shortcutPath, targetPath, true); - } - else - { - //Remove our shortcut from the startup folder for this user - _fileSystem.DeleteFile(Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "Emby Server.lnk")); - } - } - - public INetworkManager CreateNetworkManager(ILogger logger) - { - return new NetworkManager(logger); - } - - public FFMpegInstallInfo GetFfmpegInstallInfo() + protected override FFMpegInstallInfo GetFfmpegInstallInfo() { var info = new FFMpegInstallInfo(); @@ -136,7 +36,61 @@ namespace MediaBrowser.ServerApplication.Native return info; } - public void LaunchUrl(string url) + protected override void RestartInternal() + { + MainStartup.Restart(); + } + + protected override List GetAssembliesWithPartsInternal() + { + var list = new List(); + + if (!Environment.Is64BitProcess) + { + //list.Add(typeof(PismoIsoManager).Assembly); + } + + list.Add(GetType().Assembly); + + return list; + } + + protected override void ShutdownInternal() + { + MainStartup.Shutdown(); + } + + protected override void AuthorizeServer(int udpPort, int httpServerPort, int httpsServerPort, string applicationPath, string tempDirectory) + { + ServerAuthorization.AuthorizeServer(udpPort, httpServerPort, httpsServerPort, applicationPath, tempDirectory); + } + + protected override IDbConnector GetDbConnector() + { + return new DbConnector(Logger); + } + + protected override void ConfigureAutoRunInternal(bool autorun) + { + var shortcutPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.StartMenu), "Emby", "Emby Server.lnk"); + + var startupPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Startup); + + if (autorun) + { + //Copy our shortut into the startup folder for this user + var targetPath = Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "Emby Server.lnk"); + FileSystemManager.CreateDirectory(Path.GetDirectoryName(targetPath)); + File.Copy(shortcutPath, targetPath, true); + } + else + { + //Remove our shortcut from the startup folder for this user + FileSystemManager.DeleteFile(Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "Emby Server.lnk")); + } + } + + public override void LaunchUrl(string url) { var process = new Process { @@ -156,32 +110,54 @@ namespace MediaBrowser.ServerApplication.Native } catch (Exception ex) { - _logger.ErrorException("Error launching url: {0}", ex, url); + Logger.ErrorException("Error launching url: {0}", ex, url); throw; } } - public IDbConnector GetDbConnector() - { - return new DbConnector(_logger); - } - - /// - /// Processes the exited. - /// - /// The sender. - /// The instance containing the event data. private static void ProcessExited(object sender, EventArgs e) { ((Process)sender).Dispose(); } - public void EnableLoopback(string appName) + protected override void EnableLoopbackInternal(string appName) { LoopUtil.Run(appName); } + public override bool SupportsRunningAsService + { + get + { + return true; + } + } + + public override bool CanSelfRestart + { + get + { + return MainStartup.CanSelfRestart; + } + } + + public override bool SupportsAutoRunAtStartup + { + get + { + return true; + } + } + + public override bool CanSelfUpdate + { + get + { + return MainStartup.CanSelfUpdate; + } + } + public bool PortsRequireAuthorization(string applicationPath) { var appNameSrch = Path.GetFileName(applicationPath); @@ -209,7 +185,7 @@ namespace MediaBrowser.ServerApplication.Native if (data.IndexOf("Block", StringComparison.OrdinalIgnoreCase) != -1) { - _logger.Info("Found potential windows firewall rule blocking Emby Server: " + data); + Logger.Info("Found potential windows firewall rule blocking Emby Server: " + data); } //var parts = data.Split('\n'); @@ -220,7 +196,7 @@ namespace MediaBrowser.ServerApplication.Native } catch (Exception ex) { - _logger.ErrorException("Error querying windows firewall", ex); + Logger.ErrorException("Error querying windows firewall", ex); // Hate having to do this try @@ -229,12 +205,13 @@ namespace MediaBrowser.ServerApplication.Native } catch (Exception ex1) { - _logger.ErrorException("Error killing process", ex1); + Logger.ErrorException("Error killing process", ex1); } throw; } } } + } -} \ No newline at end of file +} diff --git a/src/Emby.Server/ApplicationPathHelper.cs b/src/Emby.Server/ApplicationPathHelper.cs new file mode 100644 index 000000000..4da87b6a0 --- /dev/null +++ b/src/Emby.Server/ApplicationPathHelper.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading.Tasks; + +namespace Emby.Server +{ + public class ApplicationPathHelper + { + public static string GetProgramDataPath(string applicationPath) + { + var useDebugPath = false; + +#if DEBUG + useDebugPath = true; +#endif + + var programDataPath = useDebugPath ? + "programdata" : + "programdata"; + + programDataPath = programDataPath + .Replace('/', Path.DirectorySeparatorChar) + .Replace('\\', Path.DirectorySeparatorChar); + + // If it's a relative path, e.g. "..\" + if (!Path.IsPathRooted(programDataPath)) + { + var path = Path.GetDirectoryName(applicationPath); + + if (string.IsNullOrEmpty(path)) + { + throw new Exception("Unable to determine running assembly location"); + } + + programDataPath = Path.Combine(path, programDataPath); + + programDataPath = Path.GetFullPath(programDataPath); + } + + Directory.CreateDirectory(programDataPath); + + return programDataPath; + } + } +} diff --git a/src/Emby.Server/CoreAppHost.cs b/src/Emby.Server/CoreAppHost.cs new file mode 100644 index 000000000..1a1526513 --- /dev/null +++ b/src/Emby.Server/CoreAppHost.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using Emby.Server.Core; +using Emby.Server.Core.Data; +using Emby.Server.Core.FFMpeg; +using Emby.Server.Data; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.System; + +namespace Emby.Server +{ + public class CoreAppHost : ApplicationHost + { + public CoreAppHost(ServerApplicationPaths applicationPaths, ILogManager logManager, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, IMemoryStreamFactory memoryStreamFactory, MediaBrowser.Common.Net.INetworkManager networkManager, Action certificateGenerator, Func defaultUsernameFactory) + : base(applicationPaths, logManager, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, memoryStreamFactory, networkManager, certificateGenerator, defaultUsernameFactory) + { + } + + public override bool IsRunningAsService + { + get { return false; } + } + + protected override void RestartInternal() + { + Program.Restart(); + } + + protected override void ShutdownInternal() + { + Program.Shutdown(); + } + + protected override FFMpegInstallInfo GetFfmpegInstallInfo() + { + var info = new FFMpegInstallInfo(); + + return info; + } + + protected override List GetAssembliesWithPartsInternal() + { + var list = new List(); + + list.Add(GetType().GetTypeInfo().Assembly); + + return list; + } + + protected override void AuthorizeServer(int udpPort, int httpServerPort, int httpsServerPort, string applicationPath, string tempDirectory) + { + } + + protected override IDbConnector GetDbConnector() + { + return new DbConnector(Logger); + } + + protected override void ConfigureAutoRunInternal(bool autorun) + { + } + + public override void LaunchUrl(string url) + { + } + + protected override void EnableLoopbackInternal(string appName) + { + } + + public override bool SupportsRunningAsService + { + get + { + return true; + } + } + + public override bool CanSelfRestart + { + get + { + return Program.CanSelfRestart; + } + } + + public override bool SupportsAutoRunAtStartup + { + get + { + return true; + } + } + + public override bool CanSelfUpdate + { + get + { + return Program.CanSelfUpdate; + } + } + } +} diff --git a/src/Emby.Server/CoreSystemEvents.cs b/src/Emby.Server/CoreSystemEvents.cs new file mode 100644 index 000000000..d83071fa8 --- /dev/null +++ b/src/Emby.Server/CoreSystemEvents.cs @@ -0,0 +1,11 @@ +using System; +using MediaBrowser.Model.System; + +namespace Emby.Server +{ + public class CoreSystemEvents : ISystemEvents + { + public event EventHandler Resume; + public event EventHandler Suspend; + } +} diff --git a/src/Emby.Server/Data/DbConnector.cs b/src/Emby.Server/Data/DbConnector.cs new file mode 100644 index 000000000..bd70cff6c --- /dev/null +++ b/src/Emby.Server/Data/DbConnector.cs @@ -0,0 +1,52 @@ +using System; +using System.Data; +using System.Threading.Tasks; +using MediaBrowser.Model.Logging; +using Emby.Server.Core.Data; +using Microsoft.Data.Sqlite; + +namespace Emby.Server.Data +{ + public class DbConnector : IDbConnector + { + private readonly ILogger _logger; + + public DbConnector(ILogger logger) + { + _logger = logger; + } + + public async Task Connect(string dbPath, bool isReadOnly, bool enablePooling = false, int? cacheSize = null) + { + if (string.IsNullOrEmpty(dbPath)) + { + throw new ArgumentNullException("dbPath"); + } + + //SQLiteConnection.SetMemoryStatus(false); + + var connectionstr = new SqliteConnectionStringBuilder + { + //PageSize = 4096, + //CacheSize = cacheSize ?? 2000, + //SyncMode = SynchronizationModes.Normal, + DataSource = dbPath, + //JournalMode = SQLiteJournalModeEnum.Wal, + + // This is causing crashing under linux + //Pooling = enablePooling && Environment.OSVersion.Platform == PlatformID.Win32NT, + //ReadOnly = isReadOnly, + Cache = enablePooling ? SqliteCacheMode.Default : SqliteCacheMode.Private, + Mode = isReadOnly ? SqliteOpenMode.ReadOnly : SqliteOpenMode.ReadWriteCreate + }; + + var connectionString = connectionstr.ConnectionString; + + var connection = new SqliteConnection(connectionString); + + await connection.OpenAsync().ConfigureAwait(false); + + return connection; + } + } +} \ No newline at end of file diff --git a/src/Emby.Server/IO/MemoryStreamFactory.cs b/src/Emby.Server/IO/MemoryStreamFactory.cs new file mode 100644 index 000000000..37ac2959e --- /dev/null +++ b/src/Emby.Server/IO/MemoryStreamFactory.cs @@ -0,0 +1,33 @@ +using System; +using System.IO; +using MediaBrowser.Model.IO; + +namespace Emby.Server.IO +{ + public class MemoryStreamFactory : IMemoryStreamFactory + { + public MemoryStream CreateNew() + { + return new MemoryStream(); + } + + public MemoryStream CreateNew(int capacity) + { + return new MemoryStream(capacity); + } + + public MemoryStream CreateNew(byte[] buffer) + { + return new MemoryStream(buffer); + } + + public bool TryGetBuffer(MemoryStream stream, out byte[] buffer) + { + ArraySegment arrayBuffer; + stream.TryGetBuffer(out arrayBuffer); + + buffer = arrayBuffer.Array; + return true; + } + } +} diff --git a/src/Emby.Server/PowerManagement.cs b/src/Emby.Server/PowerManagement.cs new file mode 100644 index 000000000..85e3b72a6 --- /dev/null +++ b/src/Emby.Server/PowerManagement.cs @@ -0,0 +1,15 @@ +using MediaBrowser.Model.System; + +namespace Emby.Server +{ + public class PowerManagement : IPowerManagement + { + public void PreventSystemStandby() + { + } + + public void AllowSystemStandby() + { + } + } +} diff --git a/src/Emby.Server/Program.cs b/src/Emby.Server/Program.cs index d364e7284..64fc423a1 100644 --- a/src/Emby.Server/Program.cs +++ b/src/Emby.Server/Program.cs @@ -1,33 +1,24 @@ using MediaBrowser.Model.Logging; using MediaBrowser.Server.Implementations; -using MediaBrowser.Server.Startup.Common; -using MediaBrowser.ServerApplication.Native; -using MediaBrowser.ServerApplication.Splash; -using MediaBrowser.ServerApplication.Updates; using Microsoft.Win32; using System; -using System.Configuration.Install; using System.Diagnostics; using System.IO; using System.Linq; -using System.Management; using System.Runtime.InteropServices; -using System.ServiceProcess; using System.Text; using System.Threading; using System.Threading.Tasks; -using System.Windows.Forms; using Emby.Common.Implementations.EnvironmentInfo; using Emby.Common.Implementations.IO; using Emby.Common.Implementations.Logging; using Emby.Common.Implementations.Networking; -using Emby.Common.Implementations.Security; +using Emby.Drawing; using Emby.Server.Core; using Emby.Server.Core.Browser; using Emby.Server.Implementations.IO; -using ImageMagickSharp; using MediaBrowser.Common.Net; -using MediaBrowser.Server.Startup.Common.IO; +using Emby.Server.IO; namespace Emby.Server { @@ -60,11 +51,11 @@ namespace Emby.Server var currentProcess = Process.GetCurrentProcess(); var applicationPath = currentProcess.MainModule.FileName; - var architecturePath = Path.Combine(Path.GetDirectoryName(applicationPath), Environment.Is64BitProcess ? "x64" : "x86"); + //var architecturePath = Path.Combine(Path.GetDirectoryName(applicationPath), Environment.Is64BitProcess ? "x64" : "x86"); - Wand.SetMagickCoderModulePath(architecturePath); + //Wand.SetMagickCoderModulePath(architecturePath); - var success = SetDllDirectory(architecturePath); + //var success = SetDllDirectory(architecturePath); var appPaths = CreateApplicationPaths(applicationPath, _isRunningAsService); @@ -227,31 +218,25 @@ namespace Emby.Server /// The options. private static void RunApplication(ServerApplicationPaths appPaths, ILogManager logManager, bool runService, StartupOptions options) { - var fileSystem = new WindowsFileSystem(logManager.GetLogger("FileSystem")); - fileSystem.AddShortcutHandler(new LnkShortcutHandler()); + var fileSystem = new ManagedFileSystem(logManager.GetLogger("FileSystem"), true, true, true); + fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem)); - var nativeApp = new WindowsApp(fileSystem, _logger) - { - IsRunningAsService = runService - }; + var imageEncoder = new NullImageEncoder(); - var imageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, logManager, fileSystem, options, () => _appHost.HttpClient, appPaths); - - _appHost = new ApplicationHost(appPaths, + _appHost = new CoreAppHost(appPaths, logManager, options, fileSystem, - nativeApp, new PowerManagement(), "emby.windows.zip", new EnvironmentInfo(), imageEncoder, - new Server.Startup.Common.SystemEvents(logManager.GetLogger("SystemEvents")), - new RecyclableMemoryStreamProvider(), + new CoreSystemEvents(), + new MemoryStreamFactory(), new NetworkManager(logManager.GetLogger("NetworkManager")), GenerateCertificate, - () => Environment.UserDomainName); + () => "EmbyUser"); var initProgress = new Progress(); @@ -275,12 +260,6 @@ namespace Emby.Server { Task.WaitAll(task); - task = InstallVcredist2013IfNeeded(_appHost, _logger); - Task.WaitAll(task); - - Microsoft.Win32.SystemEvents.SessionEnding += SystemEvents_SessionEnding; - Microsoft.Win32.SystemEvents.SessionSwitch += SystemEvents_SessionSwitch; - task = ApplicationTaskCompletionSource.Task; Task.WaitAll(task); } @@ -288,15 +267,7 @@ namespace Emby.Server private static void GenerateCertificate(string certPath, string certHost) { - CertificateGenerator.CreateSelfSignCertificatePfx(certPath, certHost, _logger); - } - - static void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e) - { - if (e.Reason == SessionSwitchReason.SessionLogon) - { - BrowserLauncher.OpenDashboard(_appHost); - } + //CertificateGenerator.CreateSelfSignCertificatePfx(certPath, certHost, _logger); } /// @@ -304,11 +275,6 @@ namespace Emby.Server /// private static void StartService(ILogManager logManager) { - var service = new BackgroundService(logManager.GetLogger("Service")); - - service.Disposed += service_Disposed; - - ServiceBase.Run(service); } /// @@ -329,19 +295,6 @@ namespace Emby.Server DisposeAppHost(); } - /// - /// Handles the SessionEnding event of the SystemEvents control. - /// - /// The source of the event. - /// The instance containing the event data. - static void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e) - { - if (e.Reason == SessionEndReasons.SystemShutdown || !_isRunningAsService) - { - Shutdown(); - } - } - /// /// Handles the UnhandledException event of the CurrentDomain control. /// @@ -355,7 +308,7 @@ namespace Emby.Server if (!_isRunningAsService) { - MessageBox.Show("Unhandled exception: " + exception.Message); + ShowMessageBox("Unhandled exception: " + exception.Message); } if (!Debugger.IsAttached) @@ -381,8 +334,8 @@ namespace Emby.Server // Update is there - execute update try { - var serviceName = _isRunningAsService ? BackgroundService.GetExistingServiceName() : string.Empty; - new ApplicationUpdater().UpdateApplication(appPaths, updateArchive, logger, serviceName); + //var serviceName = _isRunningAsService ? BackgroundService.GetExistingServiceName() : string.Empty; + //new ApplicationUpdater().UpdateApplication(appPaths, updateArchive, logger, serviceName); // And just let the app exit so it can update return true; @@ -391,13 +344,18 @@ namespace Emby.Server { logger.ErrorException("Error starting updater.", e); - MessageBox.Show(string.Format("Error attempting to update application.\n\n{0}\n\n{1}", e.GetType().Name, e.Message)); + ShowMessageBox(string.Format("Error attempting to update application.\n\n{0}\n\n{1}", e.GetType().Name, e.Message)); } } return false; } + private static void ShowMessageBox(string msg) + { + + } + public static void Shutdown() { if (_isRunningAsService) @@ -469,90 +427,6 @@ namespace Emby.Server return false; } - private static async Task InstallVcredist2013IfNeeded(ApplicationHost appHost, ILogger logger) - { - // Reference - // http://stackoverflow.com/questions/12206314/detect-if-visual-c-redistributable-for-visual-studio-2012-is-installed - - try - { - var subkey = Environment.Is64BitProcess - ? "SOFTWARE\\WOW6432Node\\Microsoft\\VisualStudio\\12.0\\VC\\Runtimes\\x64" - : "SOFTWARE\\Microsoft\\VisualStudio\\12.0\\VC\\Runtimes\\x86"; - - using (RegistryKey ndpKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Default) - .OpenSubKey(subkey)) - { - if (ndpKey != null && ndpKey.GetValue("Version") != null) - { - var installedVersion = ((string)ndpKey.GetValue("Version")).TrimStart('v'); - if (installedVersion.StartsWith("12", StringComparison.OrdinalIgnoreCase)) - { - return; - } - } - } - } - catch (Exception ex) - { - logger.ErrorException("Error getting .NET Framework version", ex); - return; - } - - try - { - await InstallVcredist2013().ConfigureAwait(false); - } - catch (Exception ex) - { - logger.ErrorException("Error installing Visual Studio C++ runtime", ex); - } - } - - private async static Task InstallVcredist2013() - { - var httpClient = _appHost.HttpClient; - - var tmp = await httpClient.GetTempFile(new HttpRequestOptions - { - Url = GetVcredist2013Url(), - Progress = new Progress() - - }).ConfigureAwait(false); - - var exePath = Path.ChangeExtension(tmp, ".exe"); - File.Copy(tmp, exePath); - - var startInfo = new ProcessStartInfo - { - FileName = exePath, - - CreateNoWindow = true, - WindowStyle = ProcessWindowStyle.Hidden, - Verb = "runas", - ErrorDialog = false - }; - - _logger.Info("Running {0}", startInfo.FileName); - - using (var process = Process.Start(startInfo)) - { - process.WaitForExit(); - } - } - - private static string GetVcredist2013Url() - { - if (Environment.Is64BitProcess) - { - return "https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_x64.exe"; - } - - // TODO: ARM url - https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_arm.exe - - return "https://github.com/MediaBrowser/Emby.Resources/raw/master/vcredist2013/vcredist_x86.exe"; - } - /// /// Sets the error mode. /// diff --git a/src/Emby.Server/project.json b/src/Emby.Server/project.json index 2693435a4..c64db844f 100644 --- a/src/Emby.Server/project.json +++ b/src/Emby.Server/project.json @@ -11,7 +11,11 @@ "type": "platform", "version": "1.0.1" }, - "Mono.Nat": "1.0.0-*" + "Mono.Nat": "1.0.0-*", + "Microsoft.Win32.Registry": "4.0.0", + "System.Runtime.Extensions": "4.1.0", + "System.Diagnostics.Process": "4.1.0", + "Microsoft.Data.SQLite": "1.0.0" }, "frameworks": { From 3c55747cd63fd8a69f02efbe9ac48ce76d373b81 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 13 Nov 2016 15:27:09 -0500 Subject: [PATCH 02/15] fixes #2285 - [BUG] VAAPI Transcoding (Does not work with certain codecs) --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 7 +++++-- MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs | 7 +++++-- RSSDP/RSSDP.nuget.targets | 6 ++++++ 3 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 RSSDP/RSSDP.nuget.targets diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index bac612a5b..690505869 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -336,9 +336,12 @@ namespace MediaBrowser.Api.Playback { // vaapi will throw an error with this input // [vaapi @ 0x7faed8000960] No VAAPI support for codec mpeg4 profile -99. - if (string.Equals(videoStream.Codec, "mpeg4", StringComparison.OrdinalIgnoreCase) && videoStream.Level == -99) + if (string.Equals(videoStream.Codec, "mpeg4", StringComparison.OrdinalIgnoreCase)) { - return false; + if (videoStream.Level == -99 || videoStream.Level == 15) + { + return false; + } } } return true; diff --git a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs index f811a8d48..e197bdb6f 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncodingJobFactory.cs @@ -606,9 +606,12 @@ namespace MediaBrowser.MediaEncoding.Encoder { // vaapi will throw an error with this input // [vaapi @ 0x7faed8000960] No VAAPI support for codec mpeg4 profile -99. - if (string.Equals(videoStream.Codec, "mpeg4", StringComparison.OrdinalIgnoreCase) && videoStream.Level == -99) + if (string.Equals(videoStream.Codec, "mpeg4", StringComparison.OrdinalIgnoreCase)) { - return false; + if (videoStream.Level == -99 || videoStream.Level == 15) + { + return false; + } } } return true; diff --git a/RSSDP/RSSDP.nuget.targets b/RSSDP/RSSDP.nuget.targets new file mode 100644 index 000000000..e69ce0e64 --- /dev/null +++ b/RSSDP/RSSDP.nuget.targets @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file From 0e9cd51f9c64d4cfad5cb5c7b0ddae6af8d18ac6 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 13 Nov 2016 16:04:21 -0500 Subject: [PATCH 03/15] update .net core startup --- .../BaseApplicationHost.cs | 4 +- .../BaseApplicationPaths.cs | 10 +- .../EnvironmentInfo/EnvironmentInfo.cs | 10 + .../IO/ManagedFileSystem.cs | 8 + Emby.Common.Implementations/Net/NetSocket.cs | 9 + .../Net/SocketAcceptor.cs | 24 +- .../Net/SocketFactory.cs | 7 +- Emby.Server.Core/ApplicationHost.cs | 14 +- Emby.Server.Core/Data/DataExtensions.cs | 4 +- Emby.Server.Core/Data/SqliteItemRepository.cs | 19 +- .../SqliteNotificationsRepository.cs | 2 +- Emby.Server.Core/ServerApplicationPaths.cs | 4 +- .../Channels/ChannelManager.cs | 16 +- .../HttpServer/HttpListenerHost.cs | 2 + .../LiveTv/EmbyTV/EmbyTV.cs | 92 ++++++-- .../LiveTv/EmbyTV/ItemDataProvider.cs | 3 +- .../LiveTv/LiveTvDtoService.cs | 20 +- .../LiveTv/LiveTvManager.cs | 67 ++++-- .../LiveTv/ProgramImageProvider.cs | 14 +- MediaBrowser.Api/ApiEntryPoint.cs | 6 +- .../Configuration/IApplicationPaths.cs | 6 - MediaBrowser.Controller/Entities/BaseItem.cs | 19 +- .../Encoder/EncoderValidator.cs | 18 +- MediaBrowser.Model/IO/IFileSystem.cs | 1 + MediaBrowser.Model/System/IEnvironmentInfo.cs | 2 + MediaBrowser.Server.Mono/MonoAppHost.cs | 2 +- MediaBrowser.Server.Mono/Program.cs | 10 +- .../Persistence/SqliteExtensions.cs | 6 +- MediaBrowser.ServerApplication/MainStartup.cs | 28 ++- .../Updates/ApplicationUpdater.cs | 2 +- .../WindowsAppHost.cs | 9 +- .../Savers/SeriesNfoSaver.cs | 2 - Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 +- src/Emby.Server/ApplicationPathHelper.cs | 11 +- src/Emby.Server/CoreAppHost.cs | 2 +- src/Emby.Server/Program.cs | 213 +++--------------- src/Emby.Server/project.json | 8 +- 38 files changed, 355 insertions(+), 325 deletions(-) diff --git a/Emby.Common.Implementations/BaseApplicationHost.cs b/Emby.Common.Implementations/BaseApplicationHost.cs index f0309511e..1f194968c 100644 --- a/Emby.Common.Implementations/BaseApplicationHost.cs +++ b/Emby.Common.Implementations/BaseApplicationHost.cs @@ -326,7 +326,7 @@ namespace Emby.Common.Implementations builder.AppendLine(string.Format("Processor count: {0}", Environment.ProcessorCount)); builder.AppendLine(string.Format("Program data path: {0}", appPaths.ProgramDataPath)); - builder.AppendLine(string.Format("Application Path: {0}", appPaths.ApplicationPath)); + builder.AppendLine(string.Format("Application directory: {0}", appPaths.ProgramSystemPath)); return builder; } @@ -548,7 +548,7 @@ return null; TimerFactory = new TimerFactory(); RegisterSingleInstance(TimerFactory); - SocketFactory = new SocketFactory(null); + SocketFactory = new SocketFactory(LogManager.GetLogger("SocketFactory")); RegisterSingleInstance(SocketFactory); RegisterSingleInstance(CryptographyProvider); diff --git a/Emby.Common.Implementations/BaseApplicationPaths.cs b/Emby.Common.Implementations/BaseApplicationPaths.cs index 628d62bd4..8792778ba 100644 --- a/Emby.Common.Implementations/BaseApplicationPaths.cs +++ b/Emby.Common.Implementations/BaseApplicationPaths.cs @@ -12,22 +12,18 @@ namespace Emby.Common.Implementations /// /// Initializes a new instance of the class. /// - protected BaseApplicationPaths(string programDataPath, string applicationPath) + protected BaseApplicationPaths(string programDataPath, string appFolderPath) { ProgramDataPath = programDataPath; - ApplicationPath = applicationPath; + ProgramSystemPath = appFolderPath; } - public string ApplicationPath { get; private set; } public string ProgramDataPath { get; private set; } /// /// Gets the path to the system folder /// - public string ProgramSystemPath - { - get { return Path.GetDirectoryName(ApplicationPath); } - } + public string ProgramSystemPath { get; private set; } /// /// The _data directory diff --git a/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs b/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs index 6a1b3ef74..c040e3931 100644 --- a/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs +++ b/Emby.Common.Implementations/EnvironmentInfo/EnvironmentInfo.cs @@ -95,5 +95,15 @@ namespace Emby.Common.Implementations.EnvironmentInfo return MediaBrowser.Model.System.Architecture.X64; } } + + public string GetEnvironmentVariable(string name) + { + return Environment.GetEnvironmentVariable(name); + } + + public virtual string GetUserId() + { + return null; + } } } diff --git a/Emby.Common.Implementations/IO/ManagedFileSystem.cs b/Emby.Common.Implementations/IO/ManagedFileSystem.cs index 1f0aa55fa..83bb50f94 100644 --- a/Emby.Common.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Common.Implementations/IO/ManagedFileSystem.cs @@ -57,6 +57,14 @@ namespace Emby.Common.Implementations.IO } } + public char PathSeparator + { + get + { + return Path.DirectorySeparatorChar; + } + } + public string GetFullPath(string path) { return Path.GetFullPath(path); diff --git a/Emby.Common.Implementations/Net/NetSocket.cs b/Emby.Common.Implementations/Net/NetSocket.cs index faa1a81e2..62ca3d6ac 100644 --- a/Emby.Common.Implementations/Net/NetSocket.cs +++ b/Emby.Common.Implementations/Net/NetSocket.cs @@ -15,6 +15,15 @@ namespace Emby.Common.Implementations.Net public NetSocket(Socket socket, ILogger logger) { + if (socket == null) + { + throw new ArgumentNullException("socket"); + } + if (logger == null) + { + throw new ArgumentNullException("logger"); + } + Socket = socket; _logger = logger; } diff --git a/Emby.Common.Implementations/Net/SocketAcceptor.cs b/Emby.Common.Implementations/Net/SocketAcceptor.cs index fd65e9fbc..bddb7a079 100644 --- a/Emby.Common.Implementations/Net/SocketAcceptor.cs +++ b/Emby.Common.Implementations/Net/SocketAcceptor.cs @@ -14,6 +14,23 @@ namespace Emby.Common.Implementations.Net public SocketAcceptor(ILogger logger, Socket originalSocket, Action onAccept, Func isClosed) { + if (logger == null) + { + throw new ArgumentNullException("logger"); + } + if (originalSocket == null) + { + throw new ArgumentNullException("originalSocket"); + } + if (onAccept == null) + { + throw new ArgumentNullException("onAccept"); + } + if (isClosed == null) + { + throw new ArgumentNullException("isClosed"); + } + _logger = logger; _originalSocket = originalSocket; _isClosed = isClosed; @@ -101,11 +118,8 @@ namespace Emby.Common.Implementations.Net _onAccept(new NetSocket(acceptSocket, _logger)); } - if (_originalSocket != null) - { - // Accept the next connection request - StartAccept(e, ref acceptSocket); - } + // Accept the next connection request + StartAccept(e, ref acceptSocket); } } } diff --git a/Emby.Common.Implementations/Net/SocketFactory.cs b/Emby.Common.Implementations/Net/SocketFactory.cs index 922b0f3cc..f26137683 100644 --- a/Emby.Common.Implementations/Net/SocketFactory.cs +++ b/Emby.Common.Implementations/Net/SocketFactory.cs @@ -23,10 +23,15 @@ namespace Emby.Common.Implementations.Net /// private IPAddress _LocalIP; - private ILogger _logger; + private readonly ILogger _logger; public SocketFactory(ILogger logger) { + if (logger == null) + { + throw new ArgumentNullException("logger"); + } + _logger = logger; _LocalIP = IPAddress.Any; } diff --git a/Emby.Server.Core/ApplicationHost.cs b/Emby.Server.Core/ApplicationHost.cs index 7f795a68d..d3d292ca5 100644 --- a/Emby.Server.Core/ApplicationHost.cs +++ b/Emby.Server.Core/ApplicationHost.cs @@ -725,6 +725,11 @@ namespace Emby.Server.Core try { + if (!FileSystemManager.FileExists(certificateLocation)) + { + return null; + } + X509Certificate2 localCert = new X509Certificate2(certificateLocation); //localCert.PrivateKey = PrivateKey.CreateFromFile(pvk_file).RSA; if (!localCert.HasPrivateKey) @@ -1438,12 +1443,7 @@ namespace Emby.Server.Core try { - AuthorizeServer( - UdpServerEntryPoint.PortNumber, - ServerConfigurationManager.Configuration.HttpServerPortNumber, - ServerConfigurationManager.Configuration.HttpsPortNumber, - ConfigurationManager.CommonApplicationPaths.ApplicationPath, - ConfigurationManager.CommonApplicationPaths.TempDirectory); + AuthorizeServer(); } catch (Exception ex) { @@ -1451,7 +1451,7 @@ namespace Emby.Server.Core } } - protected abstract void AuthorizeServer(int udpPort, int httpServerPort, int httpsServerPort, string applicationPath, string tempDirectory); + protected abstract void AuthorizeServer(); protected abstract IDbConnector GetDbConnector(); public event EventHandler HasUpdateAvailableChanged; diff --git a/Emby.Server.Core/Data/DataExtensions.cs b/Emby.Server.Core/Data/DataExtensions.cs index b633d9217..631c1c500 100644 --- a/Emby.Server.Core/Data/DataExtensions.cs +++ b/Emby.Server.Core/Data/DataExtensions.cs @@ -40,7 +40,7 @@ namespace Emby.Server.Core.Data public static IDataParameter Add(this IDataParameterCollection paramCollection, IDbCommand cmd, string name) { var param = cmd.CreateParameter(); - + param.ParameterName = name; paramCollection.Add(param); @@ -173,7 +173,7 @@ namespace Emby.Server.Core.Data var builder = new StringBuilder(); builder.AppendLine("alter table " + table); - builder.AppendLine("add column " + columnName + " " + type); + builder.AppendLine("add column " + columnName + " " + type + " NULL"); connection.RunQueries(new[] { builder.ToString() }, logger); } diff --git a/Emby.Server.Core/Data/SqliteItemRepository.cs b/Emby.Server.Core/Data/SqliteItemRepository.cs index 2ca86c831..6ed409aa1 100644 --- a/Emby.Server.Core/Data/SqliteItemRepository.cs +++ b/Emby.Server.Core/Data/SqliteItemRepository.cs @@ -157,7 +157,7 @@ namespace Emby.Server.Core.Data string[] queries = { - "create table if not exists TypedBaseItems (guid GUID primary key, type TEXT, data BLOB, ParentId GUID, Path TEXT)", + "create table if not exists TypedBaseItems (guid GUID primary key NOT NULL, type TEXT NOT NULL, data BLOB NULL, ParentId GUID NULL, Path TEXT NULL)", "create table if not exists AncestorIds (ItemId GUID, AncestorId GUID, AncestorIdText TEXT, PRIMARY KEY (ItemId, AncestorId))", "create index if not exists idx_AncestorIds1 on AncestorIds(AncestorId)", @@ -286,6 +286,7 @@ namespace Emby.Server.Core.Data _connection.AddColumn(Logger, "TypedBaseItems", "ExtraType", "Text"); _connection.AddColumn(Logger, "TypedBaseItems", "Artists", "Text"); _connection.AddColumn(Logger, "TypedBaseItems", "AlbumArtists", "Text"); + _connection.AddColumn(Logger, "TypedBaseItems", "ExternalId", "Text"); _connection.AddColumn(Logger, "ItemValues", "CleanValue", "Text"); @@ -440,7 +441,8 @@ namespace Emby.Server.Core.Data "TotalBitrate", "ExtraType", "Artists", - "AlbumArtists" + "AlbumArtists", + "ExternalId" }; private readonly string[] _mediaStreamSaveColumns = @@ -575,7 +577,8 @@ namespace Emby.Server.Core.Data "TotalBitrate", "ExtraType", "Artists", - "AlbumArtists" + "AlbumArtists", + "ExternalId" }; _saveItemCommand = _connection.CreateCommand(); _saveItemCommand.CommandText = "replace into TypedBaseItems (" + string.Join(",", saveColumns.ToArray()) + ") values ("; @@ -1084,6 +1087,10 @@ namespace Emby.Server.Core.Data } } + _saveItemCommand.GetParameter(index++).Value = item.ExternalId; + + //Logger.Debug(_saveItemCommand.CommandText); + _saveItemCommand.Transaction = transaction; _saveItemCommand.ExecuteNonQuery(); @@ -1967,6 +1974,12 @@ namespace Emby.Server.Core.Data } index++; + if (!reader.IsDBNull(index)) + { + item.ExternalId = reader.GetString(index); + } + index++; + if (string.IsNullOrWhiteSpace(item.Tagline)) { var movie = item as Movie; diff --git a/Emby.Server.Core/Notifications/SqliteNotificationsRepository.cs b/Emby.Server.Core/Notifications/SqliteNotificationsRepository.cs index 8a7fc9270..dee0d4cfd 100644 --- a/Emby.Server.Core/Notifications/SqliteNotificationsRepository.cs +++ b/Emby.Server.Core/Notifications/SqliteNotificationsRepository.cs @@ -30,7 +30,7 @@ namespace Emby.Server.Core.Notifications { string[] queries = { - "create table if not exists Notifications (Id GUID NOT NULL, UserId GUID NOT NULL, Date DATETIME NOT NULL, Name TEXT NOT NULL, Description TEXT, Url TEXT, Level TEXT NOT NULL, IsRead BOOLEAN NOT NULL, Category TEXT NOT NULL, RelatedId TEXT, PRIMARY KEY (Id, UserId))", + "create table if not exists Notifications (Id GUID NOT NULL, UserId GUID NOT NULL, Date DATETIME NOT NULL, Name TEXT NOT NULL, Description TEXT NULL, Url TEXT NULL, Level TEXT NOT NULL, IsRead BOOLEAN NOT NULL, Category TEXT NOT NULL, RelatedId TEXT NULL, PRIMARY KEY (Id, UserId))", "create index if not exists idx_Notifications1 on Notifications(Id)", "create index if not exists idx_Notifications2 on Notifications(UserId)" }; diff --git a/Emby.Server.Core/ServerApplicationPaths.cs b/Emby.Server.Core/ServerApplicationPaths.cs index d59dd89d9..dc80b773c 100644 --- a/Emby.Server.Core/ServerApplicationPaths.cs +++ b/Emby.Server.Core/ServerApplicationPaths.cs @@ -12,8 +12,8 @@ namespace Emby.Server.Core /// /// Initializes a new instance of the class. /// - public ServerApplicationPaths(string programDataPath, string applicationPath, string applicationResourcesPath) - : base(programDataPath, applicationPath) + public ServerApplicationPaths(string programDataPath, string appFolderPath, string applicationResourcesPath) + : base(programDataPath, appFolderPath) { ApplicationResourcesPath = applicationResourcesPath; } diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 2ce880c93..94ff7c342 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -326,7 +326,7 @@ namespace Emby.Server.Implementations.Channels if (requiresCallback != null) { - results = await GetChannelItemMediaSourcesInternal(requiresCallback, item.ExternalId, cancellationToken) + results = await GetChannelItemMediaSourcesInternal(requiresCallback, GetItemExternalId(item), cancellationToken) .ConfigureAwait(false); } else @@ -1075,6 +1075,18 @@ namespace Emby.Server.Implementations.Channels return result; } + private string GetItemExternalId(BaseItem item) + { + var externalId = item.ExternalId; + + if (string.IsNullOrWhiteSpace(externalId)) + { + externalId = item.GetProviderId("ProviderExternalId"); + } + + return externalId; + } + private readonly SemaphoreSlim _resourcePool = new SemaphoreSlim(1, 1); private async Task GetChannelItems(IChannel channel, User user, @@ -1145,7 +1157,7 @@ namespace Emby.Server.Implementations.Channels { var categoryItem = _libraryManager.GetItemById(new Guid(folderId)); - query.FolderId = categoryItem.ExternalId; + query.FolderId = GetItemExternalId(categoryItem); } var result = await channel.GetChannelItems(query, cancellationToken).ConfigureAwait(false); diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs index 41b7a4622..876d140ec 100644 --- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -396,6 +396,8 @@ namespace Emby.Server.Implementations.HttpServer if (_disposed) { httpRes.StatusCode = 503; + httpRes.ContentType = "text/plain"; + Write(httpRes, "Server shutting down"); return; } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 63356a845..aaf74b5c6 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -1551,13 +1551,28 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { try { + if (timer.IsSports) + { + AddGenre(timer.Genres, "Sports"); + } + if (timer.IsKids) + { + AddGenre(timer.Genres, "Kids"); + AddGenre(timer.Genres, "Children"); + } + if (timer.IsNews) + { + AddGenre(timer.Genres, "News"); + } + if (timer.IsProgramSeries) { SaveSeriesNfo(timer, recordingPath, seriesPath); + SaveVideoNfo(timer, recordingPath, false); } else if (!timer.IsMovie || timer.IsSports || timer.IsNews) { - SaveVideoNfo(timer, recordingPath); + SaveVideoNfo(timer, recordingPath, true); } } catch (Exception ex) @@ -1594,6 +1609,16 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV writer.WriteElementString("title", timer.Name); } + if (!string.IsNullOrEmpty(timer.OfficialRating)) + { + writer.WriteElementString("mpaa", timer.OfficialRating); + } + + foreach (var genre in timer.Genres) + { + writer.WriteElementString("genre", genre); + } + writer.WriteEndElement(); writer.WriteEndDocument(); } @@ -1601,7 +1626,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } public const string DateAddedFormat = "yyyy-MM-dd HH:mm:ss"; - private void SaveVideoNfo(TimerInfo timer, string recordingPath) + private void SaveVideoNfo(TimerInfo timer, string recordingPath, bool lockData) { var nfoPath = Path.ChangeExtension(recordingPath, ".nfo"); @@ -1622,11 +1647,41 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV using (XmlWriter writer = XmlWriter.Create(stream, settings)) { writer.WriteStartDocument(true); - writer.WriteStartElement("movie"); - if (!string.IsNullOrWhiteSpace(timer.Name)) + if (timer.IsProgramSeries) { - writer.WriteElementString("title", timer.Name); + writer.WriteStartElement("episodedetails"); + + if (!string.IsNullOrWhiteSpace(timer.EpisodeTitle)) + { + writer.WriteElementString("title", timer.EpisodeTitle); + } + + if (timer.OriginalAirDate.HasValue) + { + var formatString = _config.GetNfoConfiguration().ReleaseDateFormat; + + writer.WriteElementString("aired", timer.OriginalAirDate.Value.ToLocalTime().ToString(formatString)); + } + + if (timer.EpisodeNumber.HasValue) + { + writer.WriteElementString("episode", timer.EpisodeNumber.Value.ToString(CultureInfo.InvariantCulture)); + } + + if (timer.SeasonNumber.HasValue) + { + writer.WriteElementString("season", timer.SeasonNumber.Value.ToString(CultureInfo.InvariantCulture)); + } + } + else + { + writer.WriteStartElement("movie"); + + if (!string.IsNullOrWhiteSpace(timer.Name)) + { + writer.WriteElementString("title", timer.Name); + } } writer.WriteElementString("dateadded", DateTime.UtcNow.ToLocalTime().ToString(DateAddedFormat)); @@ -1645,27 +1700,17 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV .Replace(""", "'"); writer.WriteElementString("plot", overview); - writer.WriteElementString("lockdata", true.ToString().ToLower()); + + if (lockData) + { + writer.WriteElementString("lockdata", true.ToString().ToLower()); + } if (timer.CommunityRating.HasValue) { writer.WriteElementString("rating", timer.CommunityRating.Value.ToString(CultureInfo.InvariantCulture)); } - if (timer.IsSports) - { - AddGenre(timer.Genres, "Sports"); - } - if (timer.IsKids) - { - AddGenre(timer.Genres, "Kids"); - AddGenre(timer.Genres, "Children"); - } - if (timer.IsNews) - { - AddGenre(timer.Genres, "News"); - } - foreach (var genre in timer.Genres) { writer.WriteElementString("genre", genre); @@ -1968,4 +2013,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV public CancellationTokenSource CancellationTokenSource { get; set; } } } + public static class ConfigurationExtension + { + public static XbmcMetadataOptions GetNfoConfiguration(this IConfigurationManager manager) + { + return manager.GetConfiguration("xbmcmetadata"); + } + } } \ No newline at end of file diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs index ded4f04c4..16ae26d45 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs @@ -54,9 +54,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV catch (FileNotFoundException) { } - catch (IOException ex) + catch (IOException) { - Logger.ErrorException("Error deserializing {0}", ex, jsonFile); } catch (Exception ex) { diff --git a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs index 4e7161521..d3e30a46b 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs @@ -269,6 +269,18 @@ namespace Emby.Server.Implementations.LiveTv return _libraryManager.GetNewItemId(name.ToLower(), typeof(ILiveTvRecording)); } + private string GetItemExternalId(BaseItem item) + { + var externalId = item.ExternalId; + + if (string.IsNullOrWhiteSpace(externalId)) + { + externalId = item.GetProviderId("ProviderExternalId"); + } + + return externalId; + } + public async Task GetTimerInfo(TimerInfoDto dto, bool isNew, LiveTvManager liveTv, CancellationToken cancellationToken) { var info = new TimerInfo @@ -304,7 +316,7 @@ namespace Emby.Server.Implementations.LiveTv if (channel != null) { - info.ChannelId = channel.ExternalId; + info.ChannelId = GetItemExternalId(channel); } } @@ -314,7 +326,7 @@ namespace Emby.Server.Implementations.LiveTv if (program != null) { - info.ProgramId = program.ExternalId; + info.ProgramId = GetItemExternalId(program); } } @@ -370,7 +382,7 @@ namespace Emby.Server.Implementations.LiveTv if (channel != null) { - info.ChannelId = channel.ExternalId; + info.ChannelId = GetItemExternalId(channel); } } @@ -380,7 +392,7 @@ namespace Emby.Server.Implementations.LiveTv if (program != null) { - info.ProgramId = program.ExternalId; + info.ProgramId = GetItemExternalId(program); } } diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index adec66858..3a6f23fe9 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -251,12 +251,24 @@ namespace Emby.Server.Implementations.LiveTv return await GetLiveStream(id, mediaSourceId, true, cancellationToken).ConfigureAwait(false); } + private string GetItemExternalId(BaseItem item) + { + var externalId = item.ExternalId; + + if (string.IsNullOrWhiteSpace(externalId)) + { + externalId = item.GetProviderId("ProviderExternalId"); + } + + return externalId; + } + public async Task> GetRecordingMediaSources(IHasMediaSources item, CancellationToken cancellationToken) { var baseItem = (BaseItem)item; var service = GetService(baseItem); - return await service.GetRecordingStreamMediaSources(baseItem.ExternalId, cancellationToken).ConfigureAwait(false); + return await service.GetRecordingStreamMediaSources(GetItemExternalId(baseItem), cancellationToken).ConfigureAwait(false); } public async Task> GetChannelMediaSources(IHasMediaSources item, CancellationToken cancellationToken) @@ -313,18 +325,18 @@ namespace Emby.Server.Implementations.LiveTv var channel = GetInternalChannel(id); isVideo = channel.ChannelType == ChannelType.TV; service = GetService(channel); - _logger.Info("Opening channel stream from {0}, external channel Id: {1}", service.Name, channel.ExternalId); + _logger.Info("Opening channel stream from {0}, external channel Id: {1}", service.Name, GetItemExternalId(channel)); var supportsManagedStream = service as ISupportsDirectStreamProvider; if (supportsManagedStream != null) { - var streamInfo = await supportsManagedStream.GetChannelStreamWithDirectStreamProvider(channel.ExternalId, mediaSourceId, cancellationToken).ConfigureAwait(false); + var streamInfo = await supportsManagedStream.GetChannelStreamWithDirectStreamProvider(GetItemExternalId(channel), mediaSourceId, cancellationToken).ConfigureAwait(false); info = streamInfo.Item1; directStreamProvider = streamInfo.Item2; } else { - info = await service.GetChannelStream(channel.ExternalId, mediaSourceId, cancellationToken).ConfigureAwait(false); + info = await service.GetChannelStream(GetItemExternalId(channel), mediaSourceId, cancellationToken).ConfigureAwait(false); } info.RequiresClosing = true; @@ -341,8 +353,8 @@ namespace Emby.Server.Implementations.LiveTv isVideo = !string.Equals(recording.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase); service = GetService(recording); - _logger.Info("Opening recording stream from {0}, external recording Id: {1}", service.Name, recording.ExternalId); - info = await service.GetRecordingStream(recording.ExternalId, null, cancellationToken).ConfigureAwait(false); + _logger.Info("Opening recording stream from {0}, external recording Id: {1}", service.Name, GetItemExternalId(recording)); + info = await service.GetRecordingStream(GetItemExternalId(recording), null, cancellationToken).ConfigureAwait(false); info.RequiresClosing = true; if (info.RequiresClosing) @@ -493,7 +505,7 @@ namespace Emby.Server.Implementations.LiveTv isNew = true; } - if (!string.Equals(channelInfo.Id, item.ExternalId)) + if (!string.Equals(channelInfo.Id, item.ExternalId, StringComparison.Ordinal)) { isNew = true; } @@ -601,7 +613,6 @@ namespace Emby.Server.Implementations.LiveTv item.EpisodeTitle = info.EpisodeTitle; item.ExternalId = info.Id; - item.ExternalSeriesIdLegacy = seriesId; if (!string.IsNullOrWhiteSpace(seriesId) && !string.Equals(item.ExternalSeriesId, seriesId, StringComparison.Ordinal)) { @@ -841,6 +852,13 @@ namespace Emby.Server.Implementations.LiveTv return item.Id; } + + + private string GetExternalSeriesIdLegacy(BaseItem item) + { + return item.GetProviderId("ProviderExternalSeriesId"); + } + public async Task GetProgram(string id, CancellationToken cancellationToken, User user = null) { var program = GetInternalProgram(id); @@ -848,7 +866,15 @@ namespace Emby.Server.Implementations.LiveTv var dto = _dtoService.GetBaseItemDto(program, new DtoOptions(), user); var list = new List>(); - list.Add(new Tuple(dto, program.ServiceName, program.ExternalId, program.ExternalSeriesIdLegacy)); + + var externalSeriesId = program.ExternalSeriesId; + + if (string.IsNullOrWhiteSpace(externalSeriesId)) + { + externalSeriesId = GetExternalSeriesIdLegacy(program); + } + + list.Add(new Tuple(dto, program.ServiceName, GetItemExternalId(program), externalSeriesId)); await AddRecordingInfo(list, cancellationToken).ConfigureAwait(false); @@ -1283,7 +1309,7 @@ namespace Emby.Server.Implementations.LiveTv var isKids = false; var iSSeries = false; - var channelPrograms = await service.GetProgramsAsync(currentChannel.ExternalId, start, end, cancellationToken).ConfigureAwait(false); + var channelPrograms = await service.GetProgramsAsync(GetItemExternalId(currentChannel), start, end, cancellationToken).ConfigureAwait(false); var existingPrograms = _libraryManager.GetItemList(new InternalItemsQuery { @@ -1830,7 +1856,14 @@ namespace Emby.Server.Implementations.LiveTv dto.ServiceName = serviceName; } - programTuples.Add(new Tuple(dto, serviceName, program.ExternalId, program.ExternalSeriesIdLegacy)); + var externalSeriesId = program.ExternalSeriesId; + + if (string.IsNullOrWhiteSpace(externalSeriesId)) + { + externalSeriesId = GetExternalSeriesIdLegacy(program); + } + + programTuples.Add(new Tuple(dto, serviceName, GetItemExternalId(program), externalSeriesId)); } await AddRecordingInfo(programTuples, CancellationToken.None).ConfigureAwait(false); @@ -2006,7 +2039,7 @@ namespace Emby.Server.Implementations.LiveTv if (service is EmbyTV.EmbyTV) { // We can't trust that we'll be able to direct stream it through emby server, no matter what the provider says - return service.DeleteRecordingAsync(recording.ExternalId, CancellationToken.None); + return service.DeleteRecordingAsync(GetItemExternalId(recording), CancellationToken.None); } return Task.FromResult(true); @@ -2030,7 +2063,7 @@ namespace Emby.Server.Implementations.LiveTv try { - await service.DeleteRecordingAsync(recording.ExternalId, CancellationToken.None).ConfigureAwait(false); + await service.DeleteRecordingAsync(GetItemExternalId(recording), CancellationToken.None).ConfigureAwait(false); } catch (ResourceNotFoundException) { @@ -2289,12 +2322,12 @@ namespace Emby.Server.Implementations.LiveTv programInfo = new ProgramInfo { Audio = program.Audio, - ChannelId = channel.ExternalId, + ChannelId = GetItemExternalId(channel), CommunityRating = program.CommunityRating, EndDate = program.EndDate ?? DateTime.MinValue, EpisodeTitle = program.EpisodeTitle, Genres = program.Genres, - Id = program.ExternalId, + Id = GetItemExternalId(program), IsHD = program.IsHD, IsKids = program.IsKids, IsLive = program.IsLive, @@ -2360,7 +2393,7 @@ namespace Emby.Server.Implementations.LiveTv info.Name = program.Name; info.Overview = program.Overview; info.ProgramId = programDto.Id; - info.ExternalProgramId = program.ExternalId; + info.ExternalProgramId = GetItemExternalId(program); if (program.EndDate.HasValue) { @@ -2804,7 +2837,7 @@ namespace Emby.Server.Implementations.LiveTv public async Task SaveListingProvider(ListingsProviderInfo info, bool validateLogin, bool validateListings) { - info = _jsonSerializer.DeserializeFromString< ListingsProviderInfo>(_jsonSerializer.SerializeToString(info)); + info = _jsonSerializer.DeserializeFromString(_jsonSerializer.SerializeToString(info)); var provider = _listingProviders.FirstOrDefault(i => string.Equals(info.Type, i.Type, StringComparison.OrdinalIgnoreCase)); diff --git a/Emby.Server.Implementations/LiveTv/ProgramImageProvider.cs b/Emby.Server.Implementations/LiveTv/ProgramImageProvider.cs index f5d298af4..5a0389b16 100644 --- a/Emby.Server.Implementations/LiveTv/ProgramImageProvider.cs +++ b/Emby.Server.Implementations/LiveTv/ProgramImageProvider.cs @@ -24,6 +24,18 @@ namespace Emby.Server.Implementations.LiveTv return new[] { ImageType.Primary }; } + private string GetItemExternalId(BaseItem item) + { + var externalId = item.ExternalId; + + if (string.IsNullOrWhiteSpace(externalId)) + { + externalId = item.GetProviderId("ProviderExternalId"); + } + + return externalId; + } + public async Task GetImage(IHasImages item, ImageType type, CancellationToken cancellationToken) { var liveTvItem = (LiveTvProgram)item; @@ -38,7 +50,7 @@ namespace Emby.Server.Implementations.LiveTv { var channel = _liveTvManager.GetInternalChannel(liveTvItem.ChannelId); - var response = await service.GetProgramImageAsync(liveTvItem.ExternalId, channel.ExternalId, cancellationToken).ConfigureAwait(false); + var response = await service.GetProgramImageAsync(GetItemExternalId(liveTvItem), GetItemExternalId(channel), cancellationToken).ConfigureAwait(false); if (response != null) { diff --git a/MediaBrowser.Api/ApiEntryPoint.cs b/MediaBrowser.Api/ApiEntryPoint.cs index bc0241766..37ab12366 100644 --- a/MediaBrowser.Api/ApiEntryPoint.cs +++ b/MediaBrowser.Api/ApiEntryPoint.cs @@ -128,7 +128,11 @@ namespace MediaBrowser.Api { // Don't clutter the log } - catch (IOException ex) + catch (IOException) + { + // Don't clutter the log + } + catch (Exception ex) { Logger.ErrorException("Error deleting encoded media cache", ex); } diff --git a/MediaBrowser.Common/Configuration/IApplicationPaths.cs b/MediaBrowser.Common/Configuration/IApplicationPaths.cs index d3bf03302..d2446ce46 100644 --- a/MediaBrowser.Common/Configuration/IApplicationPaths.cs +++ b/MediaBrowser.Common/Configuration/IApplicationPaths.cs @@ -6,12 +6,6 @@ namespace MediaBrowser.Common.Configuration /// public interface IApplicationPaths { - /// - /// Gets the application path. - /// - /// The application path. - string ApplicationPath { get; } - /// /// Gets the path to the program data folder /// diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index b079da97c..10cac7992 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -296,28 +296,11 @@ namespace MediaBrowser.Controller.Entities /// If this content came from an external service, the id of the content on that service /// [IgnoreDataMember] - public string ExternalId - { - get { return this.GetProviderId("ProviderExternalId"); } - set - { - this.SetProviderId("ProviderExternalId", value); - } - } + public string ExternalId { get; set; } [IgnoreDataMember] public string ExternalSeriesId { get; set; } - [IgnoreDataMember] - public string ExternalSeriesIdLegacy - { - get { return this.GetProviderId("ProviderExternalSeriesId"); } - set - { - this.SetProviderId("ProviderExternalSeriesId", value); - } - } - /// /// Gets or sets the etag. /// diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index 6acdccf3d..1b8b3feec 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -37,15 +37,12 @@ namespace MediaBrowser.MediaEncoding.Encoder { output = GetProcessOutput(encoderAppPath, "-version"); } - catch + catch (Exception ex) { - } - - output = output ?? string.Empty; - - if (logOutput) - { - _logger.Info("ffmpeg info: {0}", output); + if (logOutput) + { + _logger.ErrorException("Error validating encoder", ex); + } } if (string.IsNullOrWhiteSpace(output)) @@ -53,6 +50,11 @@ namespace MediaBrowser.MediaEncoding.Encoder return false; } + if (logOutput) + { + _logger.Info("ffmpeg info: {0}", output); + } + if (output.IndexOf("Libav developers", StringComparison.OrdinalIgnoreCase) != -1) { return false; diff --git a/MediaBrowser.Model/IO/IFileSystem.cs b/MediaBrowser.Model/IO/IFileSystem.cs index f219d9295..22e1e7758 100644 --- a/MediaBrowser.Model/IO/IFileSystem.cs +++ b/MediaBrowser.Model/IO/IFileSystem.cs @@ -308,6 +308,7 @@ namespace MediaBrowser.Model.IO void SetReadOnly(string path, bool isHidden); char DirectorySeparatorChar { get; } + char PathSeparator { get; } string GetFullPath(string path); diff --git a/MediaBrowser.Model/System/IEnvironmentInfo.cs b/MediaBrowser.Model/System/IEnvironmentInfo.cs index c5f493e7c..7e7d81e30 100644 --- a/MediaBrowser.Model/System/IEnvironmentInfo.cs +++ b/MediaBrowser.Model/System/IEnvironmentInfo.cs @@ -12,6 +12,8 @@ namespace MediaBrowser.Model.System string OperatingSystemName { get; } string OperatingSystemVersion { get; } Architecture SystemArchitecture { get; } + string GetEnvironmentVariable(string name); + string GetUserId(); } public enum OperatingSystem diff --git a/MediaBrowser.Server.Mono/MonoAppHost.cs b/MediaBrowser.Server.Mono/MonoAppHost.cs index 5f0ecde24..fd3c9f506 100644 --- a/MediaBrowser.Server.Mono/MonoAppHost.cs +++ b/MediaBrowser.Server.Mono/MonoAppHost.cs @@ -91,7 +91,7 @@ namespace MediaBrowser.Server.Mono MainClass.Shutdown(); } - protected override void AuthorizeServer(int udpPort, int httpServerPort, int httpsServerPort, string applicationPath, string tempDirectory) + protected override void AuthorizeServer() { throw new NotImplementedException(); } diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs index 48390f078..470525ece 100644 --- a/MediaBrowser.Server.Mono/Program.cs +++ b/MediaBrowser.Server.Mono/Program.cs @@ -5,6 +5,7 @@ using MediaBrowser.Server.Startup.Common; using Microsoft.Win32; using System; using System.Diagnostics; +using System.Globalization; using System.IO; using System.Linq; using System.Net; @@ -74,7 +75,9 @@ namespace MediaBrowser.Server.Mono programDataPath = ApplicationPathHelper.GetProgramDataPath(applicationPath); } - return new ServerApplicationPaths(programDataPath, applicationPath, Path.GetDirectoryName(applicationPath)); + var appFolderPath = Path.GetDirectoryName(applicationPath); + + return new ServerApplicationPaths(programDataPath, appFolderPath, Path.GetDirectoryName(applicationPath)); } private static readonly TaskCompletionSource ApplicationTaskCompletionSource = new TaskCompletionSource(); @@ -305,5 +308,10 @@ namespace MediaBrowser.Server.Mono public class MonoEnvironmentInfo : EnvironmentInfo { public bool IsBsd { get; set; } + + public virtual string GetUserId() + { + return Syscall.getuid().ToString(CultureInfo.InvariantCulture); + } } } diff --git a/MediaBrowser.Server.Startup.Common/Persistence/SqliteExtensions.cs b/MediaBrowser.Server.Startup.Common/Persistence/SqliteExtensions.cs index 72ecfc1bf..22aeb53dd 100644 --- a/MediaBrowser.Server.Startup.Common/Persistence/SqliteExtensions.cs +++ b/MediaBrowser.Server.Startup.Common/Persistence/SqliteExtensions.cs @@ -14,7 +14,11 @@ namespace Emby.Server.Core.Data /// /// Connects to db. /// - public static async Task ConnectToDb(string dbPath, bool isReadOnly, bool enablePooling, int? cacheSize, ILogger logger) + public static async Task ConnectToDb(string dbPath, + bool isReadOnly, + bool enablePooling, + int? cacheSize, + ILogger logger) { if (string.IsNullOrEmpty(dbPath)) { diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index ab0a36aff..c0ebcde74 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -44,6 +44,8 @@ namespace MediaBrowser.ServerApplication [DllImport("kernel32.dll", SetLastError = true)] static extern bool SetDllDirectory(string lpPathName); + public static string ApplicationPath; + public static bool TryGetLocalFromUncDirectory(string local, out string unc) { if ((local == null) || (local == "")) @@ -81,14 +83,14 @@ namespace MediaBrowser.ServerApplication var currentProcess = Process.GetCurrentProcess(); - var applicationPath = currentProcess.MainModule.FileName; - var architecturePath = Path.Combine(Path.GetDirectoryName(applicationPath), Environment.Is64BitProcess ? "x64" : "x86"); + ApplicationPath = currentProcess.MainModule.FileName; + var architecturePath = Path.Combine(Path.GetDirectoryName(ApplicationPath), Environment.Is64BitProcess ? "x64" : "x86"); Wand.SetMagickCoderModulePath(architecturePath); var success = SetDllDirectory(architecturePath); - var appPaths = CreateApplicationPaths(applicationPath, IsRunningAsService); + var appPaths = CreateApplicationPaths(ApplicationPath, IsRunningAsService); var logManager = new NlogManager(appPaths.LogDirectoryPath, "server"); logManager.ReloadLogger(LogSeverity.Debug); @@ -102,7 +104,7 @@ namespace MediaBrowser.ServerApplication if (options.ContainsOption("-installservice")) { logger.Info("Performing service installation"); - InstallService(applicationPath, logger); + InstallService(ApplicationPath, logger); return; } @@ -110,7 +112,7 @@ namespace MediaBrowser.ServerApplication if (options.ContainsOption("-installserviceasadmin")) { logger.Info("Performing service installation"); - RunServiceInstallation(applicationPath); + RunServiceInstallation(ApplicationPath); return; } @@ -118,7 +120,7 @@ namespace MediaBrowser.ServerApplication if (options.ContainsOption("-uninstallservice")) { logger.Info("Performing service uninstallation"); - UninstallService(applicationPath, logger); + UninstallService(ApplicationPath, logger); return; } @@ -126,15 +128,15 @@ namespace MediaBrowser.ServerApplication if (options.ContainsOption("-uninstallserviceasadmin")) { logger.Info("Performing service uninstallation"); - RunServiceUninstallation(applicationPath); + RunServiceUninstallation(ApplicationPath); return; } AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; - RunServiceInstallationIfNeeded(applicationPath); + RunServiceInstallationIfNeeded(ApplicationPath); - if (IsAlreadyRunning(applicationPath, currentProcess)) + if (IsAlreadyRunning(ApplicationPath, currentProcess)) { logger.Info("Shutting down because another instance of Emby Server is already running."); return; @@ -250,6 +252,8 @@ namespace MediaBrowser.ServerApplication /// ServerApplicationPaths. private static ServerApplicationPaths CreateApplicationPaths(string applicationPath, bool runAsService) { + var appFolderPath = Path.GetDirectoryName(applicationPath); + var resourcesPath = Path.GetDirectoryName(applicationPath); if (runAsService) @@ -258,10 +262,10 @@ namespace MediaBrowser.ServerApplication var programDataPath = Path.GetDirectoryName(systemPath); - return new ServerApplicationPaths(programDataPath, applicationPath, resourcesPath); + return new ServerApplicationPaths(programDataPath, appFolderPath, resourcesPath); } - return new ServerApplicationPaths(ApplicationPathHelper.GetProgramDataPath(applicationPath), applicationPath, resourcesPath); + return new ServerApplicationPaths(ApplicationPathHelper.GetProgramDataPath(applicationPath), appFolderPath, resourcesPath); } /// @@ -663,7 +667,7 @@ namespace MediaBrowser.ServerApplication _logger.Info("Starting new instance"); //Application.Restart(); - Process.Start(_appHost.ServerConfigurationManager.ApplicationPaths.ApplicationPath); + Process.Start(ApplicationPath); ShutdownWindowsApplication(); } diff --git a/MediaBrowser.ServerApplication/Updates/ApplicationUpdater.cs b/MediaBrowser.ServerApplication/Updates/ApplicationUpdater.cs index c426395b7..97537b27d 100644 --- a/MediaBrowser.ServerApplication/Updates/ApplicationUpdater.cs +++ b/MediaBrowser.ServerApplication/Updates/ApplicationUpdater.cs @@ -44,7 +44,7 @@ namespace MediaBrowser.ServerApplication.Updates // startpath = executable to launch // systempath = folder containing installation var args = string.Format("product={0} archive=\"{1}\" caller={2} pismo=false version={3} service={4} installpath=\"{5}\" startpath=\"{6}\" systempath=\"{7}\"", - product, archive, Process.GetCurrentProcess().Id, version, restartServiceName ?? string.Empty, appPaths.ProgramDataPath, appPaths.ApplicationPath, systemPath); + product, archive, Process.GetCurrentProcess().Id, version, restartServiceName ?? string.Empty, appPaths.ProgramDataPath, MainStartup.ApplicationPath, systemPath); logger.Info("Args: {0}", args); Process.Start(tempUpdater, args); diff --git a/MediaBrowser.ServerApplication/WindowsAppHost.cs b/MediaBrowser.ServerApplication/WindowsAppHost.cs index 8fd718432..d9bead6b7 100644 --- a/MediaBrowser.ServerApplication/WindowsAppHost.cs +++ b/MediaBrowser.ServerApplication/WindowsAppHost.cs @@ -6,6 +6,7 @@ using System.Reflection; using Emby.Server.Core; using Emby.Server.Core.Data; using Emby.Server.Core.FFMpeg; +using Emby.Server.Implementations.EntryPoints; using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; using MediaBrowser.Model.System; @@ -60,9 +61,13 @@ namespace MediaBrowser.ServerApplication MainStartup.Shutdown(); } - protected override void AuthorizeServer(int udpPort, int httpServerPort, int httpsServerPort, string applicationPath, string tempDirectory) + protected override void AuthorizeServer() { - ServerAuthorization.AuthorizeServer(udpPort, httpServerPort, httpsServerPort, applicationPath, tempDirectory); + ServerAuthorization.AuthorizeServer(UdpServerEntryPoint.PortNumber, + ServerConfigurationManager.Configuration.HttpServerPortNumber, + ServerConfigurationManager.Configuration.HttpsPortNumber, + MainStartup.ApplicationPath, + ConfigurationManager.CommonApplicationPaths.TempDirectory); } protected override IDbConnector GetDbConnector() diff --git a/MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs index 4c22f0246..b512939a7 100644 --- a/MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs @@ -90,8 +90,6 @@ namespace MediaBrowser.XbmcMetadata.Savers } } - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - protected override List GetTagsUsed() { var list = new List diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 464a29eb2..daeb754ba 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.689 + 3.0.691 Emby.Common Emby Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index 96e9a697a..a34a9bee2 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.689 + 3.0.691 Emby.Server.Core Emby Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Emby Server. Copyright © Emby 2013 - + diff --git a/src/Emby.Server/ApplicationPathHelper.cs b/src/Emby.Server/ApplicationPathHelper.cs index 4da87b6a0..c611ff372 100644 --- a/src/Emby.Server/ApplicationPathHelper.cs +++ b/src/Emby.Server/ApplicationPathHelper.cs @@ -8,7 +8,7 @@ namespace Emby.Server { public class ApplicationPathHelper { - public static string GetProgramDataPath(string applicationPath) + public static string GetProgramDataPath(string appDirectory) { var useDebugPath = false; @@ -27,14 +27,7 @@ namespace Emby.Server // If it's a relative path, e.g. "..\" if (!Path.IsPathRooted(programDataPath)) { - var path = Path.GetDirectoryName(applicationPath); - - if (string.IsNullOrEmpty(path)) - { - throw new Exception("Unable to determine running assembly location"); - } - - programDataPath = Path.Combine(path, programDataPath); + programDataPath = Path.Combine(appDirectory, programDataPath); programDataPath = Path.GetFullPath(programDataPath); } diff --git a/src/Emby.Server/CoreAppHost.cs b/src/Emby.Server/CoreAppHost.cs index 1a1526513..21f6ae445 100644 --- a/src/Emby.Server/CoreAppHost.cs +++ b/src/Emby.Server/CoreAppHost.cs @@ -51,7 +51,7 @@ namespace Emby.Server return list; } - protected override void AuthorizeServer(int udpPort, int httpServerPort, int httpsServerPort, string applicationPath, string tempDirectory) + protected override void AuthorizeServer() { } diff --git a/src/Emby.Server/Program.cs b/src/Emby.Server/Program.cs index 64fc423a1..6f871990d 100644 --- a/src/Emby.Server/Program.cs +++ b/src/Emby.Server/Program.cs @@ -28,8 +28,6 @@ namespace Emby.Server private static ILogger _logger; - private static bool _isRunningAsService = false; - private static bool _canRestartService = false; private static bool _appHostDisposed; [DllImport("kernel32.dll", SetLastError = true)] @@ -41,39 +39,33 @@ namespace Emby.Server public static void Main(string[] args) { var options = new StartupOptions(); - _isRunningAsService = options.ContainsOption("-service"); - - if (_isRunningAsService) - { - //_canRestartService = CanRestartWindowsService(); - } var currentProcess = Process.GetCurrentProcess(); - - var applicationPath = currentProcess.MainModule.FileName; + + var baseDirectory = System.AppContext.BaseDirectory; //var architecturePath = Path.Combine(Path.GetDirectoryName(applicationPath), Environment.Is64BitProcess ? "x64" : "x86"); //Wand.SetMagickCoderModulePath(architecturePath); //var success = SetDllDirectory(architecturePath); - var appPaths = CreateApplicationPaths(applicationPath, _isRunningAsService); + var appPaths = CreateApplicationPaths(baseDirectory); var logManager = new NlogManager(appPaths.LogDirectoryPath, "server"); logManager.ReloadLogger(LogSeverity.Debug); logManager.AddConsoleOutput(); var logger = _logger = logManager.GetLogger("Main"); - + ApplicationHost.LogEnvironmentInfo(logger, appPaths, true); AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; - if (IsAlreadyRunning(applicationPath, currentProcess)) - { - logger.Info("Shutting down because another instance of Emby Server is already running."); - return; - } + //if (IsAlreadyRunning(applicationPath, currentProcess)) + //{ + // logger.Info("Shutting down because another instance of Emby Server is already running."); + // return; + //} if (PerformUpdateIfNeeded(appPaths, logger)) { @@ -81,14 +73,7 @@ namespace Emby.Server return; } - try - { - RunApplication(appPaths, logManager, _isRunningAsService, options); - } - finally - { - OnServiceShutdown(); - } + RunApplication(appPaths, logManager, options); } /// @@ -139,34 +124,17 @@ namespace Emby.Server } } - if (!_isRunningAsService) - { - return false; - } - return false; } /// /// Creates the application paths. /// - /// The application path. - /// if set to true [run as service]. - /// ServerApplicationPaths. - private static ServerApplicationPaths CreateApplicationPaths(string applicationPath, bool runAsService) + private static ServerApplicationPaths CreateApplicationPaths(string appDirectory) { - var resourcesPath = Path.GetDirectoryName(applicationPath); + var resourcesPath = appDirectory; - if (runAsService) - { - var systemPath = Path.GetDirectoryName(applicationPath); - - var programDataPath = Path.GetDirectoryName(systemPath); - - return new ServerApplicationPaths(programDataPath, applicationPath, resourcesPath); - } - - return new ServerApplicationPaths(ApplicationPathHelper.GetProgramDataPath(applicationPath), applicationPath, resourcesPath); + return new ServerApplicationPaths(ApplicationPathHelper.GetProgramDataPath(appDirectory), appDirectory, resourcesPath); } /// @@ -177,14 +145,7 @@ namespace Emby.Server { get { - if (_isRunningAsService) - { - return _canRestartService; - } - else - { - return true; - } + return true; } } @@ -196,14 +157,7 @@ namespace Emby.Server { get { - if (_isRunningAsService) - { - return _canRestartService; - } - else - { - return true; - } + return false; } } @@ -214,9 +168,8 @@ namespace Emby.Server /// /// The app paths. /// The log manager. - /// if set to true [run service]. /// The options. - private static void RunApplication(ServerApplicationPaths appPaths, ILogManager logManager, bool runService, StartupOptions options) + private static void RunApplication(ServerApplicationPaths appPaths, ILogManager logManager, StartupOptions options) { var fileSystem = new ManagedFileSystem(logManager.GetLogger("FileSystem"), true, true, true); @@ -240,29 +193,19 @@ namespace Emby.Server var initProgress = new Progress(); - if (!runService) - { - // Not crazy about this but it's the only way to suppress ffmpeg crash dialog boxes - SetErrorMode(ErrorModes.SEM_FAILCRITICALERRORS | ErrorModes.SEM_NOALIGNMENTFAULTEXCEPT | - ErrorModes.SEM_NOGPFAULTERRORBOX | ErrorModes.SEM_NOOPENFILEERRORBOX); - } + // Not crazy about this but it's the only way to suppress ffmpeg crash dialog boxes + SetErrorMode(ErrorModes.SEM_FAILCRITICALERRORS | ErrorModes.SEM_NOALIGNMENTFAULTEXCEPT | + ErrorModes.SEM_NOGPFAULTERRORBOX | ErrorModes.SEM_NOOPENFILEERRORBOX); var task = _appHost.Init(initProgress); Task.WaitAll(task); task = task.ContinueWith(new Action(a => _appHost.RunStartupTasks()), TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.AttachedToParent); - if (runService) - { - StartService(logManager); - } - else - { - Task.WaitAll(task); + Task.WaitAll(task); - task = ApplicationTaskCompletionSource.Task; - Task.WaitAll(task); - } + task = ApplicationTaskCompletionSource.Task; + Task.WaitAll(task); } private static void GenerateCertificate(string certPath, string certHost) @@ -270,31 +213,6 @@ namespace Emby.Server //CertificateGenerator.CreateSelfSignCertificatePfx(certPath, certHost, _logger); } - /// - /// Starts the service. - /// - private static void StartService(ILogManager logManager) - { - } - - /// - /// Handles the Disposed event of the service control. - /// - /// The source of the event. - /// The instance containing the event data. - static void service_Disposed(object sender, EventArgs e) - { - ApplicationTaskCompletionSource.SetResult(true); - OnServiceShutdown(); - } - - private static void OnServiceShutdown() - { - _logger.Info("Shutting down"); - - DisposeAppHost(); - } - /// /// Handles the UnhandledException event of the CurrentDomain control. /// @@ -306,10 +224,7 @@ namespace Emby.Server new UnhandledExceptionWriter(_appHost.ServerConfigurationManager.ApplicationPaths, _logger, _appHost.LogManager).Log(exception); - if (!_isRunningAsService) - { - ShowMessageBox("Unhandled exception: " + exception.Message); - } + ShowMessageBox("Unhandled exception: " + exception.Message); if (!Debugger.IsAttached) { @@ -325,29 +240,6 @@ namespace Emby.Server /// true if XXXX, false otherwise private static bool PerformUpdateIfNeeded(ServerApplicationPaths appPaths, ILogger logger) { - // Look for the existence of an update archive - var updateArchive = Path.Combine(appPaths.TempUpdatePath, "MBServer" + ".zip"); - if (File.Exists(updateArchive)) - { - logger.Info("An update is available from {0}", updateArchive); - - // Update is there - execute update - try - { - //var serviceName = _isRunningAsService ? BackgroundService.GetExistingServiceName() : string.Empty; - //new ApplicationUpdater().UpdateApplication(appPaths, updateArchive, logger, serviceName); - - // And just let the app exit so it can update - return true; - } - catch (Exception e) - { - logger.ErrorException("Error starting updater.", e); - - ShowMessageBox(string.Format("Error attempting to update application.\n\n{0}\n\n{1}", e.GetType().Name, e.Message)); - } - } - return false; } @@ -358,37 +250,25 @@ namespace Emby.Server public static void Shutdown() { - if (_isRunningAsService) - { - ShutdownWindowsService(); - } - else - { - DisposeAppHost(); + DisposeAppHost(); - ShutdownWindowsApplication(); - } + //_logger.Info("Calling Application.Exit"); + //Application.Exit(); + + _logger.Info("Calling Environment.Exit"); + Environment.Exit(0); + + _logger.Info("Calling ApplicationTaskCompletionSource.SetResult"); + ApplicationTaskCompletionSource.SetResult(true); } public static void Restart() { DisposeAppHost(); - if (_isRunningAsService) - { - RestartWindowsService(); - } - else - { - //_logger.Info("Hiding server notify icon"); - //_serverNotifyIcon.Visible = false; + // todo: start new instance - _logger.Info("Starting new instance"); - //Application.Restart(); - Process.Start(_appHost.ServerConfigurationManager.ApplicationPaths.ApplicationPath); - - ShutdownWindowsApplication(); - } + Shutdown(); } private static void DisposeAppHost() @@ -402,31 +282,6 @@ namespace Emby.Server } } - private static void ShutdownWindowsApplication() - { - //_logger.Info("Calling Application.Exit"); - //Application.Exit(); - - _logger.Info("Calling Environment.Exit"); - Environment.Exit(0); - - _logger.Info("Calling ApplicationTaskCompletionSource.SetResult"); - ApplicationTaskCompletionSource.SetResult(true); - } - - private static void ShutdownWindowsService() - { - } - - private static void RestartWindowsService() - { - } - - private static bool CanRestartWindowsService() - { - return false; - } - /// /// Sets the error mode. /// diff --git a/src/Emby.Server/project.json b/src/Emby.Server/project.json index c64db844f..55acee514 100644 --- a/src/Emby.Server/project.json +++ b/src/Emby.Server/project.json @@ -12,10 +12,10 @@ "version": "1.0.1" }, "Mono.Nat": "1.0.0-*", - "Microsoft.Win32.Registry": "4.0.0", - "System.Runtime.Extensions": "4.1.0", - "System.Diagnostics.Process": "4.1.0", - "Microsoft.Data.SQLite": "1.0.0" + "Microsoft.Win32.Registry": "4.0.0", + "System.Runtime.Extensions": "4.1.0", + "System.Diagnostics.Process": "4.1.0", + "Microsoft.Data.SQLite": "1.1.0-preview1-final" }, "frameworks": { From 635c8d50a361dc2eabbeea0ae55048d1e9f4ad8f Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 13 Nov 2016 22:44:54 -0500 Subject: [PATCH 04/15] update character escaping --- .../Channels/ChannelManager.cs | 17 +++++++++++-- .../Security/MBLicenseFile.cs | 12 ++++++--- .../Encoder/MediaEncoder.cs | 10 +++----- MediaBrowser.Model/Dlna/StreamBuilder.cs | 2 +- .../WindowsAppHost.cs | 25 +++++++++++++++++-- 5 files changed, 52 insertions(+), 14 deletions(-) diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 94ff7c342..0df916ded 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -1108,7 +1108,11 @@ namespace Emby.Server.Implementations.Channels { if (_fileSystem.GetLastWriteTimeUtc(cachePath).Add(cacheLength) > DateTime.UtcNow) { - return _jsonSerializer.DeserializeFromFile(cachePath); + var cachedResult = _jsonSerializer.DeserializeFromFile(cachePath); + if (cachedResult != null) + { + return cachedResult; + } } } } @@ -1131,7 +1135,11 @@ namespace Emby.Server.Implementations.Channels { if (_fileSystem.GetLastWriteTimeUtc(cachePath).Add(cacheLength) > DateTime.UtcNow) { - return _jsonSerializer.DeserializeFromFile(cachePath); + var cachedResult = _jsonSerializer.DeserializeFromFile(cachePath); + if (cachedResult != null) + { + return cachedResult; + } } } } @@ -1162,6 +1170,11 @@ namespace Emby.Server.Implementations.Channels var result = await channel.GetChannelItems(query, cancellationToken).ConfigureAwait(false); + if (result == null) + { + throw new InvalidOperationException("Channel returned a null result from GetChannelItems"); + } + if (!startIndex.HasValue && !limit.HasValue) { CacheResponse(result, cachePath); diff --git a/Emby.Server.Implementations/Security/MBLicenseFile.cs b/Emby.Server.Implementations/Security/MBLicenseFile.cs index 4b6a82b6c..76741bdf8 100644 --- a/Emby.Server.Implementations/Security/MBLicenseFile.cs +++ b/Emby.Server.Implementations/Security/MBLicenseFile.cs @@ -57,9 +57,14 @@ namespace Emby.Server.Implementations.Security _updateRecords.AddOrUpdate(key, value, (k, v) => value); } + private Guid GetKey(string featureId) + { + return new Guid(_cryptographyProvider.ComputeMD5(Encoding.Unicode.GetBytes(featureId))); + } + public void AddRegCheck(string featureId) { - var key = new Guid(_cryptographyProvider.ComputeMD5(Encoding.Unicode.GetBytes(featureId))); + var key = GetKey(featureId); var value = DateTime.UtcNow; SetUpdateRecord(key, value); @@ -68,7 +73,7 @@ namespace Emby.Server.Implementations.Security public void RemoveRegCheck(string featureId) { - var key = new Guid(_cryptographyProvider.ComputeMD5(Encoding.Unicode.GetBytes(featureId))); + var key = GetKey(featureId); DateTime val; _updateRecords.TryRemove(key, out val); @@ -78,8 +83,9 @@ namespace Emby.Server.Implementations.Security public DateTime LastChecked(string featureId) { + var key = GetKey(featureId); DateTime last; - _updateRecords.TryGetValue(new Guid(_cryptographyProvider.ComputeMD5(Encoding.Unicode.GetBytes(featureId))), out last); + _updateRecords.TryGetValue(key, out last); // guard agains people just putting a large number in the file return last < DateTime.UtcNow ? last : DateTime.MinValue; diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index bae367d82..a52ac0e60 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -88,8 +88,8 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly int DefaultImageExtractionTimeoutMs; private readonly bool EnableEncoderFontFile; - public MediaEncoder(ILogger logger, IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, bool hasExternalEncoder, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILiveTvManager liveTvManager, IIsoManager isoManager, ILibraryManager libraryManager, IChannelManager channelManager, ISessionManager sessionManager, Func subtitleEncoder, Func mediaSourceManager, IHttpClient httpClient, IZipClient zipClient, IMemoryStreamFactory memoryStreamProvider, IProcessFactory processFactory, - int defaultImageExtractionTimeoutMs, + public MediaEncoder(ILogger logger, IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, bool hasExternalEncoder, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILiveTvManager liveTvManager, IIsoManager isoManager, ILibraryManager libraryManager, IChannelManager channelManager, ISessionManager sessionManager, Func subtitleEncoder, Func mediaSourceManager, IHttpClient httpClient, IZipClient zipClient, IMemoryStreamFactory memoryStreamProvider, IProcessFactory processFactory, + int defaultImageExtractionTimeoutMs, bool enableEncoderFontFile) { _logger = logger; @@ -459,7 +459,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (request.AnalyzeDurationSections > 0) { analyzeDuration = "-analyzeduration " + - (request.AnalyzeDurationSections*1000000).ToString(CultureInfo.InvariantCulture); + (request.AnalyzeDurationSections * 1000000).ToString(CultureInfo.InvariantCulture); } else { @@ -1221,9 +1221,7 @@ namespace MediaBrowser.MediaEncoding.Encoder // https://ffmpeg.org/ffmpeg-filters.html#Notes-on-filtergraph-escaping // We need to double escape - var escapeChars = new[] {':', '\'', ','}; - - return path.Replace('\\', '/').Replace(":/", "\\:/").Replace("'", "'\\\\\\''"); + return path.Replace('\\', '/').Replace(":", "\\:").Replace("'", "'\\\\\\''"); } /// diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 06a883c06..c11cfb523 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -976,7 +976,7 @@ namespace MediaBrowser.Model.Dlna if (item.Bitrate.Value > maxBitrate.Value) { - _logger.Info("Bitrate exceeds DirectPlay limit"); + _logger.Info("Bitrate exceeds DirectPlay limit: media bitrate: {0}, max bitrate: {1}", item.Bitrate.Value.ToString(CultureInfo.InvariantCulture), maxBitrate.Value.ToString(CultureInfo.InvariantCulture)); return false; } diff --git a/MediaBrowser.ServerApplication/WindowsAppHost.cs b/MediaBrowser.ServerApplication/WindowsAppHost.cs index d9bead6b7..fa18b5229 100644 --- a/MediaBrowser.ServerApplication/WindowsAppHost.cs +++ b/MediaBrowser.ServerApplication/WindowsAppHost.cs @@ -32,11 +32,32 @@ namespace MediaBrowser.ServerApplication info.FFMpegFilename = "ffmpeg.exe"; info.FFProbeFilename = "ffprobe.exe"; - info.Version = "0"; + info.Version = "20160410"; + info.ArchiveType = "7z"; + info.DownloadUrls = GetDownloadUrls(); return info; } + private string[] GetDownloadUrls() + { + switch (EnvironmentInfo.SystemArchitecture) + { + case Architecture.X64: + return new[] + { + "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20160410-win64.7z" + }; + case Architecture.X86: + return new[] + { + "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/windows/ffmpeg-20160410-win32.7z" + }; + } + + return new string[] { }; + } + protected override void RestartInternal() { MainStartup.Restart(); @@ -80,7 +101,7 @@ namespace MediaBrowser.ServerApplication var shortcutPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.StartMenu), "Emby", "Emby Server.lnk"); var startupPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Startup); - + if (autorun) { //Copy our shortut into the startup folder for this user From a01eddd9695271d0ddd79d450cfbbc2fc70237b1 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 13 Nov 2016 22:53:06 -0500 Subject: [PATCH 05/15] update mac project --- MediaBrowser.Server.Mac.sln | 729 ++++++++++++++++++++++++------------ 1 file changed, 495 insertions(+), 234 deletions(-) diff --git a/MediaBrowser.Server.Mac.sln b/MediaBrowser.Server.Mac.sln index d1e2e4621..9b04284c3 100644 --- a/MediaBrowser.Server.Mac.sln +++ b/MediaBrowser.Server.Mac.sln @@ -1,18 +1,16 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Server.Mac", "MediaBrowser.Server.Mac\Emby.Server.Mac.csproj", "{C97B98FA-00D4-4880-88B8-C76017A418AB}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Api", "MediaBrowser.Api\MediaBrowser.Api.csproj", "{4FD51AC5-2C16-4308-A993-C3A84F3B4582}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Common", "MediaBrowser.Common\MediaBrowser.Common.csproj", "{9142EEFA-7570-41E1-BFCC-468BB571AF2F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Common.Implementations", "MediaBrowser.Common.Implementations\MediaBrowser.Common.Implementations.csproj", "{C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Controller", "MediaBrowser.Controller\MediaBrowser.Controller.csproj", "{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Dlna", "MediaBrowser.Dlna\MediaBrowser.Dlna.csproj", "{734098EB-6DC1-4DD0-A1CA-3140DCD2737C}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.LocalMetadata", "MediaBrowser.LocalMetadata\MediaBrowser.LocalMetadata.csproj", "{7EF9F3E0-697D-42F3-A08F-19DEB5F84392}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.MediaEncoding", "MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj", "{0BD82FA6-EB8A-4452-8AF5-74F9C3849451}" @@ -33,231 +31,43 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenSubtitlesHandler", "Ope EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Drawing", "Emby.Drawing\Emby.Drawing.csproj", "{08FFF49B-F175-4807-A2B5-73B0EBD9F716}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Nat", "Mono.Nat\Mono.Nat.csproj", "{D7453B88-2266-4805-B39B-2B5A2A33E1BA}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BDInfo", "BDInfo\BDInfo.csproj", "{88AE38DF-19D7-406F-A6A9-09527719A21E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DvdLib", "DvdLib\DvdLib.csproj", "{713F42B5-878E-499D-A878-E4C652B1D5E8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Dlna", "Emby.Dlna\Emby.Dlna.csproj", "{805844AB-E92F-45E6-9D99-4F6D48D129A5}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Drawing.ImageMagick", "Emby.Drawing.ImageMagick\Emby.Drawing.ImageMagick.csproj", "{6CFEE013-6E7C-432B-AC37-CABF0880C69A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Drawing.Net", "Emby.Drawing.Net\Emby.Drawing.Net.csproj", "{C97A239E-A96C-4D64-A844-CCF8CC30AECB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Photos", "Emby.Photos\Emby.Photos.csproj", "{89AB4548-770D-41FD-A891-8DAFF44F452C}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Emby.Server.Implementations", "Emby.Server.Implementations\Emby.Server.Implementations.csproj", "{E383961B-9356-4D5D-8233-9A1079D03055}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RSSDP", "RSSDP\RSSDP.csproj", "{21002819-C39A-4D3E-BE83-2A276A77FB1F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SocketHttpListener.Portable", "SocketHttpListener.Portable\SocketHttpListener.Portable.csproj", "{4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ServiceStack", "ServiceStack\ServiceStack.csproj", "{680A1709-25EB-4D52-A87F-EE03FFD94BAA}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU AppStore|Any CPU = AppStore|Any CPU - Release Mono|Any CPU = Release Mono|Any CPU + AppStore|x86 = AppStore|x86 + Debug|Any CPU = Debug|Any CPU Debug|x86 = Debug|x86 - Release|x86 = Release|x86 + Release Mono|Any CPU = Release Mono|Any CPU Release Mono|x86 = Release Mono|x86 + Release|Any CPU = Release|Any CPU + Release|x86 = Release|x86 + Signed|Any CPU = Signed|Any CPU + Signed|x86 = Signed|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.AppStore|Any CPU.Build.0 = Release|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Any CPU.Build.0 = Debug|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|x86.ActiveCfg = Debug|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|x86.Build.0 = Debug|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release Mono|Any CPU.ActiveCfg = Debug|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release Mono|Any CPU.Build.0 = Debug|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release Mono|x86.ActiveCfg = Debug|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release Mono|x86.Build.0 = Debug|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|Any CPU.ActiveCfg = Release|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|Any CPU.Build.0 = Release|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|x86.ActiveCfg = Release|Any CPU - {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|x86.Build.0 = Release|Any CPU - {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.AppStore|Any CPU.Build.0 = Release|Any CPU - {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|x86.ActiveCfg = Debug|Any CPU - {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|x86.Build.0 = Debug|Any CPU - {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU - {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU - {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release Mono|x86.ActiveCfg = Release Mono|Any CPU - {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release Mono|x86.Build.0 = Release Mono|Any CPU - {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|Any CPU.Build.0 = Release|Any CPU - {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|x86.ActiveCfg = Release|Any CPU - {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|x86.Build.0 = Release|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.AppStore|Any CPU.Build.0 = Release|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|x86.ActiveCfg = Debug|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|x86.Build.0 = Debug|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release Mono|x86.ActiveCfg = Release Mono|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release Mono|x86.Build.0 = Release Mono|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|Any CPU.Build.0 = Release|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|x86.ActiveCfg = Release|Any CPU - {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|x86.Build.0 = Release|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.AppStore|Any CPU.Build.0 = Release|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.Debug|x86.ActiveCfg = Debug|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.Debug|x86.Build.0 = Debug|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.Release Mono|Any CPU.ActiveCfg = Debug|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.Release Mono|Any CPU.Build.0 = Debug|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.Release Mono|x86.ActiveCfg = Debug|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.Release Mono|x86.Build.0 = Debug|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.Release|Any CPU.Build.0 = Release|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.Release|x86.ActiveCfg = Release|Any CPU - {23499896-B135-4527-8574-C26E926EA99E}.Release|x86.Build.0 = Release|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.AppStore|Any CPU.Build.0 = Release|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Debug|x86.ActiveCfg = Debug|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Debug|x86.Build.0 = Debug|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Release Mono|x86.ActiveCfg = Release Mono|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Release Mono|x86.Build.0 = Release Mono|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Release|Any CPU.Build.0 = Release|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Release|x86.ActiveCfg = Release|Any CPU - {2E781478-814D-4A48-9D80-BFF206441A65}.Release|x86.Build.0 = Release|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.AppStore|Any CPU.Build.0 = Release|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|x86.ActiveCfg = Debug|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|x86.Build.0 = Debug|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release Mono|x86.ActiveCfg = Release Mono|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release Mono|x86.Build.0 = Release Mono|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Any CPU.Build.0 = Release|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|x86.ActiveCfg = Release|Any CPU - {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|x86.Build.0 = Release|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.AppStore|Any CPU.Build.0 = Release|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|x86.ActiveCfg = Debug|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|x86.Build.0 = Debug|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release Mono|x86.ActiveCfg = Release Mono|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release Mono|x86.Build.0 = Release Mono|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|Any CPU.Build.0 = Release|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|x86.ActiveCfg = Release|Any CPU - {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|x86.Build.0 = Release|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.AppStore|Any CPU.Build.0 = Release|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|x86.ActiveCfg = Debug|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|x86.Build.0 = Debug|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release Mono|x86.ActiveCfg = Release Mono|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release Mono|x86.Build.0 = Release Mono|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|Any CPU.Build.0 = Release|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|x86.ActiveCfg = Release|Any CPU - {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|x86.Build.0 = Release|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.AppStore|Any CPU.Build.0 = Release|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|x86.ActiveCfg = Debug|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|x86.Build.0 = Debug|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release Mono|x86.ActiveCfg = Release Mono|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release Mono|x86.Build.0 = Release Mono|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|Any CPU.Build.0 = Release|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|x86.ActiveCfg = Release|Any CPU - {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|x86.Build.0 = Release|Any CPU - {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.AppStore|Any CPU.Build.0 = Release|Any CPU - {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug|x86.ActiveCfg = Debug|Any CPU - {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Debug|x86.Build.0 = Debug|Any CPU - {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU - {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU - {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release Mono|x86.ActiveCfg = Release Mono|Any CPU - {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release Mono|x86.Build.0 = Release Mono|Any CPU - {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|Any CPU.Build.0 = Release|Any CPU - {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|x86.ActiveCfg = Release|Any CPU - {734098EB-6DC1-4DD0-A1CA-3140DCD2737C}.Release|x86.Build.0 = Release|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.AppStore|Any CPU.Build.0 = Release|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|x86.ActiveCfg = Debug|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|x86.Build.0 = Debug|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release Mono|x86.ActiveCfg = Release Mono|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release Mono|x86.Build.0 = Release Mono|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|Any CPU.Build.0 = Release|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|x86.ActiveCfg = Release|Any CPU - {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|x86.Build.0 = Release|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.AppStore|Any CPU.Build.0 = Release|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|x86.ActiveCfg = Debug|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|x86.Build.0 = Debug|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release Mono|Any CPU.ActiveCfg = Debug|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release Mono|Any CPU.Build.0 = Debug|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release Mono|x86.ActiveCfg = Debug|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release Mono|x86.Build.0 = Debug|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Any CPU.Build.0 = Release|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|x86.ActiveCfg = Release|Any CPU - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|x86.Build.0 = Release|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.AppStore|Any CPU.Build.0 = Release|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|x86.ActiveCfg = Debug|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|x86.Build.0 = Debug|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release Mono|x86.ActiveCfg = Release Mono|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release Mono|x86.Build.0 = Release Mono|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|Any CPU.Build.0 = Release|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|x86.ActiveCfg = Release|Any CPU - {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|x86.Build.0 = Release|Any CPU - {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.AppStore|Any CPU.Build.0 = Release|Any CPU - {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Debug|x86.ActiveCfg = Debug|Any CPU - {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Debug|x86.Build.0 = Debug|Any CPU - {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Release Mono|Any CPU.ActiveCfg = Debug|Any CPU - {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Release Mono|Any CPU.Build.0 = Debug|Any CPU - {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Release Mono|x86.ActiveCfg = Debug|Any CPU - {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Release Mono|x86.Build.0 = Debug|Any CPU - {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Release|Any CPU.Build.0 = Release|Any CPU - {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Release|x86.ActiveCfg = Release|Any CPU - {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Release|x86.Build.0 = Release|Any CPU - {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.AppStore|Any CPU.ActiveCfg = Release|Any CPU - {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.AppStore|Any CPU.Build.0 = Release|Any CPU - {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Debug|x86.ActiveCfg = Debug|Any CPU - {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Debug|x86.Build.0 = Debug|Any CPU - {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU - {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU - {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release Mono|x86.ActiveCfg = Release Mono|Any CPU - {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release Mono|x86.Build.0 = Release Mono|Any CPU - {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release|Any CPU.Build.0 = Release|Any CPU - {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release|x86.ActiveCfg = Release|Any CPU - {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D}.Release|x86.Build.0 = Release|Any CPU {C97B98FA-00D4-4880-88B8-C76017A418AB}.AppStore|Any CPU.ActiveCfg = AppStore|Any CPU {C97B98FA-00D4-4880-88B8-C76017A418AB}.AppStore|Any CPU.Build.0 = AppStore|Any CPU + {C97B98FA-00D4-4880-88B8-C76017A418AB}.AppStore|x86.ActiveCfg = AppStore|Any CPU {C97B98FA-00D4-4880-88B8-C76017A418AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C97B98FA-00D4-4880-88B8-C76017A418AB}.Debug|Any CPU.Build.0 = Debug|Any CPU {C97B98FA-00D4-4880-88B8-C76017A418AB}.Debug|x86.ActiveCfg = Debug|Any CPU @@ -270,20 +80,471 @@ Global {C97B98FA-00D4-4880-88B8-C76017A418AB}.Release|Any CPU.Build.0 = Release|Any CPU {C97B98FA-00D4-4880-88B8-C76017A418AB}.Release|x86.ActiveCfg = Release|Any CPU {C97B98FA-00D4-4880-88B8-C76017A418AB}.Release|x86.Build.0 = Release|Any CPU - {D7453B88-2266-4805-B39B-2B5A2A33E1BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D7453B88-2266-4805-B39B-2B5A2A33E1BA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D7453B88-2266-4805-B39B-2B5A2A33E1BA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D7453B88-2266-4805-B39B-2B5A2A33E1BA}.Release|Any CPU.Build.0 = Release|Any CPU - {D7453B88-2266-4805-B39B-2B5A2A33E1BA}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU - {D7453B88-2266-4805-B39B-2B5A2A33E1BA}.AppStore|Any CPU.Build.0 = Debug|Any CPU - {D7453B88-2266-4805-B39B-2B5A2A33E1BA}.Release Mono|Any CPU.ActiveCfg = Debug|Any CPU - {D7453B88-2266-4805-B39B-2B5A2A33E1BA}.Release Mono|Any CPU.Build.0 = Debug|Any CPU - {D7453B88-2266-4805-B39B-2B5A2A33E1BA}.Debug|x86.ActiveCfg = Debug|Any CPU - {D7453B88-2266-4805-B39B-2B5A2A33E1BA}.Debug|x86.Build.0 = Debug|Any CPU - {D7453B88-2266-4805-B39B-2B5A2A33E1BA}.Release|x86.ActiveCfg = Release|Any CPU - {D7453B88-2266-4805-B39B-2B5A2A33E1BA}.Release|x86.Build.0 = Release|Any CPU - {D7453B88-2266-4805-B39B-2B5A2A33E1BA}.Release Mono|x86.ActiveCfg = Debug|Any CPU - {D7453B88-2266-4805-B39B-2B5A2A33E1BA}.Release Mono|x86.Build.0 = Debug|Any CPU + {C97B98FA-00D4-4880-88B8-C76017A418AB}.Signed|Any CPU.ActiveCfg = Release|Any CPU + {C97B98FA-00D4-4880-88B8-C76017A418AB}.Signed|x86.ActiveCfg = Release|Any CPU + {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.AppStore|Any CPU.Build.0 = Release|Any CPU + {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.AppStore|x86.ActiveCfg = Release Mono|Any CPU + {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.AppStore|x86.Build.0 = Release Mono|Any CPU + {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|x86.ActiveCfg = Debug|Any CPU + {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|x86.Build.0 = Debug|Any CPU + {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU + {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU + {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release Mono|x86.ActiveCfg = Release Mono|Any CPU + {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release Mono|x86.Build.0 = Release Mono|Any CPU + {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|Any CPU.Build.0 = Release|Any CPU + {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|x86.ActiveCfg = Release|Any CPU + {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|x86.Build.0 = Release|Any CPU + {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Signed|Any CPU.ActiveCfg = Release Mono|Any CPU + {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Signed|Any CPU.Build.0 = Release Mono|Any CPU + {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Signed|x86.ActiveCfg = Release Mono|Any CPU + {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Signed|x86.Build.0 = Release Mono|Any CPU + {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.AppStore|Any CPU.Build.0 = Release|Any CPU + {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.AppStore|x86.ActiveCfg = Release Mono|Any CPU + {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.AppStore|x86.Build.0 = Release Mono|Any CPU + {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|x86.ActiveCfg = Debug|Any CPU + {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|x86.Build.0 = Debug|Any CPU + {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU + {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU + {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release Mono|x86.ActiveCfg = Release Mono|Any CPU + {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release Mono|x86.Build.0 = Release Mono|Any CPU + {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|Any CPU.Build.0 = Release|Any CPU + {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|x86.ActiveCfg = Release|Any CPU + {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|x86.Build.0 = Release|Any CPU + {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Signed|Any CPU.ActiveCfg = Release Mono|Any CPU + {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Signed|Any CPU.Build.0 = Release Mono|Any CPU + {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Signed|x86.ActiveCfg = Release Mono|Any CPU + {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Signed|x86.Build.0 = Release Mono|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.AppStore|Any CPU.Build.0 = Release|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.AppStore|x86.ActiveCfg = Release Mono|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.AppStore|x86.Build.0 = Release Mono|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|x86.ActiveCfg = Debug|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|x86.Build.0 = Debug|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release Mono|x86.ActiveCfg = Release Mono|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release Mono|x86.Build.0 = Release Mono|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|Any CPU.Build.0 = Release|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|x86.ActiveCfg = Release|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|x86.Build.0 = Release|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Signed|Any CPU.ActiveCfg = Release Mono|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Signed|Any CPU.Build.0 = Release Mono|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Signed|x86.ActiveCfg = Release Mono|Any CPU + {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Signed|x86.Build.0 = Release Mono|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.AppStore|Any CPU.Build.0 = Release|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.AppStore|x86.ActiveCfg = Debug|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.AppStore|x86.Build.0 = Debug|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|x86.ActiveCfg = Debug|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|x86.Build.0 = Debug|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release Mono|Any CPU.ActiveCfg = Debug|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release Mono|Any CPU.Build.0 = Debug|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release Mono|x86.ActiveCfg = Debug|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release Mono|x86.Build.0 = Debug|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Any CPU.Build.0 = Release|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|x86.ActiveCfg = Release|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|x86.Build.0 = Release|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Signed|Any CPU.ActiveCfg = Debug|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Signed|Any CPU.Build.0 = Debug|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Signed|x86.ActiveCfg = Debug|Any CPU + {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Signed|x86.Build.0 = Debug|Any CPU + {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.AppStore|Any CPU.Build.0 = Release|Any CPU + {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.AppStore|x86.ActiveCfg = Release Mono|Any CPU + {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.AppStore|x86.Build.0 = Release Mono|Any CPU + {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|x86.ActiveCfg = Debug|Any CPU + {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Debug|x86.Build.0 = Debug|Any CPU + {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU + {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU + {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release Mono|x86.ActiveCfg = Release Mono|Any CPU + {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release Mono|x86.Build.0 = Release Mono|Any CPU + {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|Any CPU.Build.0 = Release|Any CPU + {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|x86.ActiveCfg = Release|Any CPU + {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Release|x86.Build.0 = Release|Any CPU + {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Signed|Any CPU.ActiveCfg = Release Mono|Any CPU + {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Signed|Any CPU.Build.0 = Release Mono|Any CPU + {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Signed|x86.ActiveCfg = Release Mono|Any CPU + {0BD82FA6-EB8A-4452-8AF5-74F9C3849451}.Signed|x86.Build.0 = Release Mono|Any CPU + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.AppStore|Any CPU.Build.0 = Release|Any CPU + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.AppStore|x86.ActiveCfg = Debug|Any CPU + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.AppStore|x86.Build.0 = Debug|Any CPU + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|x86.ActiveCfg = Debug|Any CPU + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|x86.Build.0 = Debug|Any CPU + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release Mono|Any CPU.Build.0 = Release|Any CPU + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release Mono|x86.ActiveCfg = Release|Any CPU + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release Mono|x86.Build.0 = Release|Any CPU + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|Any CPU.Build.0 = Release|Any CPU + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|x86.ActiveCfg = Release|Any CPU + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|x86.Build.0 = Release|Any CPU + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Signed|Any CPU.ActiveCfg = Debug|Any CPU + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Signed|Any CPU.Build.0 = Debug|Any CPU + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Signed|x86.ActiveCfg = Debug|Any CPU + {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Signed|x86.Build.0 = Debug|Any CPU + {442B5058-DCAF-4263-BB6A-F21E31120A1B}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {442B5058-DCAF-4263-BB6A-F21E31120A1B}.AppStore|Any CPU.Build.0 = Release|Any CPU + {442B5058-DCAF-4263-BB6A-F21E31120A1B}.AppStore|x86.ActiveCfg = Release Mono|Any CPU + {442B5058-DCAF-4263-BB6A-F21E31120A1B}.AppStore|x86.Build.0 = Release Mono|Any CPU + {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|x86.ActiveCfg = Debug|Any CPU + {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|x86.Build.0 = Debug|Any CPU + {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU + {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU + {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release Mono|x86.ActiveCfg = Release Mono|Any CPU + {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release Mono|x86.Build.0 = Release Mono|Any CPU + {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Any CPU.Build.0 = Release|Any CPU + {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|x86.ActiveCfg = Release|Any CPU + {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|x86.Build.0 = Release|Any CPU + {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Signed|Any CPU.ActiveCfg = Release Mono|Any CPU + {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Signed|Any CPU.Build.0 = Release Mono|Any CPU + {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Signed|x86.ActiveCfg = Release Mono|Any CPU + {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Signed|x86.Build.0 = Release Mono|Any CPU + {2E781478-814D-4A48-9D80-BFF206441A65}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {2E781478-814D-4A48-9D80-BFF206441A65}.AppStore|Any CPU.Build.0 = Release|Any CPU + {2E781478-814D-4A48-9D80-BFF206441A65}.AppStore|x86.ActiveCfg = Release Mono|Any CPU + {2E781478-814D-4A48-9D80-BFF206441A65}.AppStore|x86.Build.0 = Release Mono|Any CPU + {2E781478-814D-4A48-9D80-BFF206441A65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E781478-814D-4A48-9D80-BFF206441A65}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E781478-814D-4A48-9D80-BFF206441A65}.Debug|x86.ActiveCfg = Debug|Any CPU + {2E781478-814D-4A48-9D80-BFF206441A65}.Debug|x86.Build.0 = Debug|Any CPU + {2E781478-814D-4A48-9D80-BFF206441A65}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU + {2E781478-814D-4A48-9D80-BFF206441A65}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU + {2E781478-814D-4A48-9D80-BFF206441A65}.Release Mono|x86.ActiveCfg = Release Mono|Any CPU + {2E781478-814D-4A48-9D80-BFF206441A65}.Release Mono|x86.Build.0 = Release Mono|Any CPU + {2E781478-814D-4A48-9D80-BFF206441A65}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E781478-814D-4A48-9D80-BFF206441A65}.Release|Any CPU.Build.0 = Release|Any CPU + {2E781478-814D-4A48-9D80-BFF206441A65}.Release|x86.ActiveCfg = Release|Any CPU + {2E781478-814D-4A48-9D80-BFF206441A65}.Release|x86.Build.0 = Release|Any CPU + {2E781478-814D-4A48-9D80-BFF206441A65}.Signed|Any CPU.ActiveCfg = Release Mono|Any CPU + {2E781478-814D-4A48-9D80-BFF206441A65}.Signed|Any CPU.Build.0 = Release Mono|Any CPU + {2E781478-814D-4A48-9D80-BFF206441A65}.Signed|x86.ActiveCfg = Release Mono|Any CPU + {2E781478-814D-4A48-9D80-BFF206441A65}.Signed|x86.Build.0 = Release Mono|Any CPU + {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.AppStore|Any CPU.Build.0 = Release|Any CPU + {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.AppStore|x86.ActiveCfg = Debug|Any CPU + {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.AppStore|x86.Build.0 = Debug|Any CPU + {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Debug|x86.ActiveCfg = Debug|Any CPU + {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Debug|x86.Build.0 = Debug|Any CPU + {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Release Mono|Any CPU.ActiveCfg = Debug|Any CPU + {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Release Mono|Any CPU.Build.0 = Debug|Any CPU + {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Release Mono|x86.ActiveCfg = Debug|Any CPU + {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Release Mono|x86.Build.0 = Debug|Any CPU + {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Release|Any CPU.Build.0 = Release|Any CPU + {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Release|x86.ActiveCfg = Release|Any CPU + {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Release|x86.Build.0 = Release|Any CPU + {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Signed|Any CPU.ActiveCfg = Debug|Any CPU + {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Signed|Any CPU.Build.0 = Debug|Any CPU + {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Signed|x86.ActiveCfg = Debug|Any CPU + {B90AB8F2-1BFF-4568-A3FD-2A338A435A75}.Signed|x86.Build.0 = Debug|Any CPU + {5624B7B5-B5A7-41D8-9F10-CC5611109619}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {5624B7B5-B5A7-41D8-9F10-CC5611109619}.AppStore|Any CPU.Build.0 = Release|Any CPU + {5624B7B5-B5A7-41D8-9F10-CC5611109619}.AppStore|x86.ActiveCfg = Release Mono|Any CPU + {5624B7B5-B5A7-41D8-9F10-CC5611109619}.AppStore|x86.Build.0 = Release Mono|Any CPU + {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|x86.ActiveCfg = Debug|Any CPU + {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|x86.Build.0 = Debug|Any CPU + {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU + {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU + {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release Mono|x86.ActiveCfg = Release Mono|Any CPU + {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release Mono|x86.Build.0 = Release Mono|Any CPU + {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|Any CPU.Build.0 = Release|Any CPU + {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|x86.ActiveCfg = Release|Any CPU + {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|x86.Build.0 = Release|Any CPU + {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Signed|Any CPU.ActiveCfg = Release Mono|Any CPU + {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Signed|Any CPU.Build.0 = Release Mono|Any CPU + {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Signed|x86.ActiveCfg = Release Mono|Any CPU + {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Signed|x86.Build.0 = Release Mono|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.AppStore|Any CPU.Build.0 = Release|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.AppStore|x86.ActiveCfg = Debug|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.AppStore|x86.Build.0 = Debug|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Debug|x86.ActiveCfg = Debug|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Debug|x86.Build.0 = Debug|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Release Mono|Any CPU.ActiveCfg = Debug|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Release Mono|Any CPU.Build.0 = Debug|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Release Mono|x86.ActiveCfg = Debug|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Release Mono|x86.Build.0 = Debug|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Release|Any CPU.Build.0 = Release|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Release|x86.ActiveCfg = Release|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Release|x86.Build.0 = Release|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Signed|Any CPU.ActiveCfg = Debug|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Signed|Any CPU.Build.0 = Debug|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Signed|x86.ActiveCfg = Debug|Any CPU + {23499896-B135-4527-8574-C26E926EA99E}.Signed|x86.Build.0 = Debug|Any CPU + {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.AppStore|Any CPU.Build.0 = Release|Any CPU + {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.AppStore|x86.ActiveCfg = Release Mono|Any CPU + {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.AppStore|x86.Build.0 = Release Mono|Any CPU + {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|x86.ActiveCfg = Debug|Any CPU + {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|x86.Build.0 = Debug|Any CPU + {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release Mono|Any CPU.ActiveCfg = Release Mono|Any CPU + {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release Mono|Any CPU.Build.0 = Release Mono|Any CPU + {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release Mono|x86.ActiveCfg = Release Mono|Any CPU + {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release Mono|x86.Build.0 = Release Mono|Any CPU + {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|Any CPU.Build.0 = Release|Any CPU + {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|x86.ActiveCfg = Release|Any CPU + {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|x86.Build.0 = Release|Any CPU + {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Signed|Any CPU.ActiveCfg = Release Mono|Any CPU + {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Signed|Any CPU.Build.0 = Release Mono|Any CPU + {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Signed|x86.ActiveCfg = Release Mono|Any CPU + {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Signed|x86.Build.0 = Release Mono|Any CPU + {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.AppStore|Any CPU.Build.0 = Release|Any CPU + {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.AppStore|x86.ActiveCfg = Debug|Any CPU + {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.AppStore|x86.Build.0 = Debug|Any CPU + {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Any CPU.Build.0 = Debug|Any CPU + {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|x86.ActiveCfg = Debug|Any CPU + {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|x86.Build.0 = Debug|Any CPU + {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release Mono|Any CPU.ActiveCfg = Debug|Any CPU + {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release Mono|Any CPU.Build.0 = Debug|Any CPU + {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release Mono|x86.ActiveCfg = Debug|Any CPU + {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release Mono|x86.Build.0 = Debug|Any CPU + {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|Any CPU.ActiveCfg = Release|Any CPU + {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|Any CPU.Build.0 = Release|Any CPU + {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|x86.ActiveCfg = Release|Any CPU + {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|x86.Build.0 = Release|Any CPU + {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Signed|Any CPU.ActiveCfg = Debug|Any CPU + {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Signed|Any CPU.Build.0 = Debug|Any CPU + {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Signed|x86.ActiveCfg = Debug|Any CPU + {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Signed|x86.Build.0 = Debug|Any CPU + {88AE38DF-19D7-406F-A6A9-09527719A21E}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {88AE38DF-19D7-406F-A6A9-09527719A21E}.AppStore|Any CPU.Build.0 = Release|Any CPU + {88AE38DF-19D7-406F-A6A9-09527719A21E}.AppStore|x86.ActiveCfg = Release|Any CPU + {88AE38DF-19D7-406F-A6A9-09527719A21E}.AppStore|x86.Build.0 = Release|Any CPU + {88AE38DF-19D7-406F-A6A9-09527719A21E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {88AE38DF-19D7-406F-A6A9-09527719A21E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {88AE38DF-19D7-406F-A6A9-09527719A21E}.Debug|x86.ActiveCfg = Debug|Any CPU + {88AE38DF-19D7-406F-A6A9-09527719A21E}.Debug|x86.Build.0 = Debug|Any CPU + {88AE38DF-19D7-406F-A6A9-09527719A21E}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU + {88AE38DF-19D7-406F-A6A9-09527719A21E}.Release Mono|Any CPU.Build.0 = Release|Any CPU + {88AE38DF-19D7-406F-A6A9-09527719A21E}.Release Mono|x86.ActiveCfg = Release|Any CPU + {88AE38DF-19D7-406F-A6A9-09527719A21E}.Release Mono|x86.Build.0 = Release|Any CPU + {88AE38DF-19D7-406F-A6A9-09527719A21E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {88AE38DF-19D7-406F-A6A9-09527719A21E}.Release|Any CPU.Build.0 = Release|Any CPU + {88AE38DF-19D7-406F-A6A9-09527719A21E}.Release|x86.ActiveCfg = Release|Any CPU + {88AE38DF-19D7-406F-A6A9-09527719A21E}.Release|x86.Build.0 = Release|Any CPU + {88AE38DF-19D7-406F-A6A9-09527719A21E}.Signed|Any CPU.ActiveCfg = Release|Any CPU + {88AE38DF-19D7-406F-A6A9-09527719A21E}.Signed|Any CPU.Build.0 = Release|Any CPU + {88AE38DF-19D7-406F-A6A9-09527719A21E}.Signed|x86.ActiveCfg = Release|Any CPU + {88AE38DF-19D7-406F-A6A9-09527719A21E}.Signed|x86.Build.0 = Release|Any CPU + {713F42B5-878E-499D-A878-E4C652B1D5E8}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {713F42B5-878E-499D-A878-E4C652B1D5E8}.AppStore|Any CPU.Build.0 = Release|Any CPU + {713F42B5-878E-499D-A878-E4C652B1D5E8}.AppStore|x86.ActiveCfg = Release|Any CPU + {713F42B5-878E-499D-A878-E4C652B1D5E8}.AppStore|x86.Build.0 = Release|Any CPU + {713F42B5-878E-499D-A878-E4C652B1D5E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {713F42B5-878E-499D-A878-E4C652B1D5E8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {713F42B5-878E-499D-A878-E4C652B1D5E8}.Debug|x86.ActiveCfg = Debug|Any CPU + {713F42B5-878E-499D-A878-E4C652B1D5E8}.Debug|x86.Build.0 = Debug|Any CPU + {713F42B5-878E-499D-A878-E4C652B1D5E8}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU + {713F42B5-878E-499D-A878-E4C652B1D5E8}.Release Mono|Any CPU.Build.0 = Release|Any CPU + {713F42B5-878E-499D-A878-E4C652B1D5E8}.Release Mono|x86.ActiveCfg = Release|Any CPU + {713F42B5-878E-499D-A878-E4C652B1D5E8}.Release Mono|x86.Build.0 = Release|Any CPU + {713F42B5-878E-499D-A878-E4C652B1D5E8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {713F42B5-878E-499D-A878-E4C652B1D5E8}.Release|Any CPU.Build.0 = Release|Any CPU + {713F42B5-878E-499D-A878-E4C652B1D5E8}.Release|x86.ActiveCfg = Release|Any CPU + {713F42B5-878E-499D-A878-E4C652B1D5E8}.Release|x86.Build.0 = Release|Any CPU + {713F42B5-878E-499D-A878-E4C652B1D5E8}.Signed|Any CPU.ActiveCfg = Release|Any CPU + {713F42B5-878E-499D-A878-E4C652B1D5E8}.Signed|Any CPU.Build.0 = Release|Any CPU + {713F42B5-878E-499D-A878-E4C652B1D5E8}.Signed|x86.ActiveCfg = Release|Any CPU + {713F42B5-878E-499D-A878-E4C652B1D5E8}.Signed|x86.Build.0 = Release|Any CPU + {805844AB-E92F-45E6-9D99-4F6D48D129A5}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {805844AB-E92F-45E6-9D99-4F6D48D129A5}.AppStore|Any CPU.Build.0 = Release|Any CPU + {805844AB-E92F-45E6-9D99-4F6D48D129A5}.AppStore|x86.ActiveCfg = Release|Any CPU + {805844AB-E92F-45E6-9D99-4F6D48D129A5}.AppStore|x86.Build.0 = Release|Any CPU + {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Debug|x86.ActiveCfg = Debug|Any CPU + {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Debug|x86.Build.0 = Debug|Any CPU + {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU + {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release Mono|Any CPU.Build.0 = Release|Any CPU + {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release Mono|x86.ActiveCfg = Release|Any CPU + {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release Mono|x86.Build.0 = Release|Any CPU + {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release|Any CPU.Build.0 = Release|Any CPU + {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release|x86.ActiveCfg = Release|Any CPU + {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release|x86.Build.0 = Release|Any CPU + {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Signed|Any CPU.ActiveCfg = Release|Any CPU + {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Signed|Any CPU.Build.0 = Release|Any CPU + {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Signed|x86.ActiveCfg = Release|Any CPU + {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Signed|x86.Build.0 = Release|Any CPU + {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.AppStore|Any CPU.Build.0 = Release|Any CPU + {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.AppStore|x86.ActiveCfg = Release|Any CPU + {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.AppStore|x86.Build.0 = Release|Any CPU + {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Debug|x86.ActiveCfg = Debug|Any CPU + {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Debug|x86.Build.0 = Debug|Any CPU + {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU + {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release Mono|Any CPU.Build.0 = Release|Any CPU + {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release Mono|x86.ActiveCfg = Release|Any CPU + {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release Mono|x86.Build.0 = Release|Any CPU + {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release|Any CPU.Build.0 = Release|Any CPU + {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release|x86.ActiveCfg = Release|Any CPU + {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Release|x86.Build.0 = Release|Any CPU + {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Signed|Any CPU.ActiveCfg = Release|Any CPU + {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Signed|Any CPU.Build.0 = Release|Any CPU + {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Signed|x86.ActiveCfg = Release|Any CPU + {6CFEE013-6E7C-432B-AC37-CABF0880C69A}.Signed|x86.Build.0 = Release|Any CPU + {C97A239E-A96C-4D64-A844-CCF8CC30AECB}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {C97A239E-A96C-4D64-A844-CCF8CC30AECB}.AppStore|Any CPU.Build.0 = Release|Any CPU + {C97A239E-A96C-4D64-A844-CCF8CC30AECB}.AppStore|x86.ActiveCfg = Release|Any CPU + {C97A239E-A96C-4D64-A844-CCF8CC30AECB}.AppStore|x86.Build.0 = Release|Any CPU + {C97A239E-A96C-4D64-A844-CCF8CC30AECB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C97A239E-A96C-4D64-A844-CCF8CC30AECB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C97A239E-A96C-4D64-A844-CCF8CC30AECB}.Debug|x86.ActiveCfg = Debug|Any CPU + {C97A239E-A96C-4D64-A844-CCF8CC30AECB}.Debug|x86.Build.0 = Debug|Any CPU + {C97A239E-A96C-4D64-A844-CCF8CC30AECB}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU + {C97A239E-A96C-4D64-A844-CCF8CC30AECB}.Release Mono|Any CPU.Build.0 = Release|Any CPU + {C97A239E-A96C-4D64-A844-CCF8CC30AECB}.Release Mono|x86.ActiveCfg = Release|Any CPU + {C97A239E-A96C-4D64-A844-CCF8CC30AECB}.Release Mono|x86.Build.0 = Release|Any CPU + {C97A239E-A96C-4D64-A844-CCF8CC30AECB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C97A239E-A96C-4D64-A844-CCF8CC30AECB}.Release|Any CPU.Build.0 = Release|Any CPU + {C97A239E-A96C-4D64-A844-CCF8CC30AECB}.Release|x86.ActiveCfg = Release|Any CPU + {C97A239E-A96C-4D64-A844-CCF8CC30AECB}.Release|x86.Build.0 = Release|Any CPU + {C97A239E-A96C-4D64-A844-CCF8CC30AECB}.Signed|Any CPU.ActiveCfg = Release|Any CPU + {C97A239E-A96C-4D64-A844-CCF8CC30AECB}.Signed|Any CPU.Build.0 = Release|Any CPU + {C97A239E-A96C-4D64-A844-CCF8CC30AECB}.Signed|x86.ActiveCfg = Release|Any CPU + {C97A239E-A96C-4D64-A844-CCF8CC30AECB}.Signed|x86.Build.0 = Release|Any CPU + {89AB4548-770D-41FD-A891-8DAFF44F452C}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {89AB4548-770D-41FD-A891-8DAFF44F452C}.AppStore|Any CPU.Build.0 = Release|Any CPU + {89AB4548-770D-41FD-A891-8DAFF44F452C}.AppStore|x86.ActiveCfg = Release|Any CPU + {89AB4548-770D-41FD-A891-8DAFF44F452C}.AppStore|x86.Build.0 = Release|Any CPU + {89AB4548-770D-41FD-A891-8DAFF44F452C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {89AB4548-770D-41FD-A891-8DAFF44F452C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {89AB4548-770D-41FD-A891-8DAFF44F452C}.Debug|x86.ActiveCfg = Debug|Any CPU + {89AB4548-770D-41FD-A891-8DAFF44F452C}.Debug|x86.Build.0 = Debug|Any CPU + {89AB4548-770D-41FD-A891-8DAFF44F452C}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU + {89AB4548-770D-41FD-A891-8DAFF44F452C}.Release Mono|Any CPU.Build.0 = Release|Any CPU + {89AB4548-770D-41FD-A891-8DAFF44F452C}.Release Mono|x86.ActiveCfg = Release|Any CPU + {89AB4548-770D-41FD-A891-8DAFF44F452C}.Release Mono|x86.Build.0 = Release|Any CPU + {89AB4548-770D-41FD-A891-8DAFF44F452C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {89AB4548-770D-41FD-A891-8DAFF44F452C}.Release|Any CPU.Build.0 = Release|Any CPU + {89AB4548-770D-41FD-A891-8DAFF44F452C}.Release|x86.ActiveCfg = Release|Any CPU + {89AB4548-770D-41FD-A891-8DAFF44F452C}.Release|x86.Build.0 = Release|Any CPU + {89AB4548-770D-41FD-A891-8DAFF44F452C}.Signed|Any CPU.ActiveCfg = Release|Any CPU + {89AB4548-770D-41FD-A891-8DAFF44F452C}.Signed|Any CPU.Build.0 = Release|Any CPU + {89AB4548-770D-41FD-A891-8DAFF44F452C}.Signed|x86.ActiveCfg = Release|Any CPU + {89AB4548-770D-41FD-A891-8DAFF44F452C}.Signed|x86.Build.0 = Release|Any CPU + {E383961B-9356-4D5D-8233-9A1079D03055}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {E383961B-9356-4D5D-8233-9A1079D03055}.AppStore|Any CPU.Build.0 = Release|Any CPU + {E383961B-9356-4D5D-8233-9A1079D03055}.AppStore|x86.ActiveCfg = Release|Any CPU + {E383961B-9356-4D5D-8233-9A1079D03055}.AppStore|x86.Build.0 = Release|Any CPU + {E383961B-9356-4D5D-8233-9A1079D03055}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E383961B-9356-4D5D-8233-9A1079D03055}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E383961B-9356-4D5D-8233-9A1079D03055}.Debug|x86.ActiveCfg = Debug|Any CPU + {E383961B-9356-4D5D-8233-9A1079D03055}.Debug|x86.Build.0 = Debug|Any CPU + {E383961B-9356-4D5D-8233-9A1079D03055}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU + {E383961B-9356-4D5D-8233-9A1079D03055}.Release Mono|Any CPU.Build.0 = Release|Any CPU + {E383961B-9356-4D5D-8233-9A1079D03055}.Release Mono|x86.ActiveCfg = Release|Any CPU + {E383961B-9356-4D5D-8233-9A1079D03055}.Release Mono|x86.Build.0 = Release|Any CPU + {E383961B-9356-4D5D-8233-9A1079D03055}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E383961B-9356-4D5D-8233-9A1079D03055}.Release|Any CPU.Build.0 = Release|Any CPU + {E383961B-9356-4D5D-8233-9A1079D03055}.Release|x86.ActiveCfg = Release|Any CPU + {E383961B-9356-4D5D-8233-9A1079D03055}.Release|x86.Build.0 = Release|Any CPU + {E383961B-9356-4D5D-8233-9A1079D03055}.Signed|Any CPU.ActiveCfg = Release|Any CPU + {E383961B-9356-4D5D-8233-9A1079D03055}.Signed|Any CPU.Build.0 = Release|Any CPU + {E383961B-9356-4D5D-8233-9A1079D03055}.Signed|x86.ActiveCfg = Release|Any CPU + {E383961B-9356-4D5D-8233-9A1079D03055}.Signed|x86.Build.0 = Release|Any CPU + {21002819-C39A-4D3E-BE83-2A276A77FB1F}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {21002819-C39A-4D3E-BE83-2A276A77FB1F}.AppStore|Any CPU.Build.0 = Release|Any CPU + {21002819-C39A-4D3E-BE83-2A276A77FB1F}.AppStore|x86.ActiveCfg = Release|Any CPU + {21002819-C39A-4D3E-BE83-2A276A77FB1F}.AppStore|x86.Build.0 = Release|Any CPU + {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Debug|x86.ActiveCfg = Debug|Any CPU + {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Debug|x86.Build.0 = Debug|Any CPU + {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU + {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release Mono|Any CPU.Build.0 = Release|Any CPU + {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release Mono|x86.ActiveCfg = Release|Any CPU + {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release Mono|x86.Build.0 = Release|Any CPU + {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release|Any CPU.Build.0 = Release|Any CPU + {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release|x86.ActiveCfg = Release|Any CPU + {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release|x86.Build.0 = Release|Any CPU + {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Signed|Any CPU.ActiveCfg = Release|Any CPU + {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Signed|Any CPU.Build.0 = Release|Any CPU + {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Signed|x86.ActiveCfg = Release|Any CPU + {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Signed|x86.Build.0 = Release|Any CPU + {4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.AppStore|Any CPU.ActiveCfg = Release|Any CPU + {4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.AppStore|Any CPU.Build.0 = Release|Any CPU + {4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.AppStore|x86.ActiveCfg = Release|Any CPU + {4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.AppStore|x86.Build.0 = Release|Any CPU + {4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.Debug|x86.ActiveCfg = Debug|Any CPU + {4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.Debug|x86.Build.0 = Debug|Any CPU + {4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU + {4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.Release Mono|Any CPU.Build.0 = Release|Any CPU + {4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.Release Mono|x86.ActiveCfg = Release|Any CPU + {4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.Release Mono|x86.Build.0 = Release|Any CPU + {4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.Release|Any CPU.Build.0 = Release|Any CPU + {4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.Release|x86.ActiveCfg = Release|Any CPU + {4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.Release|x86.Build.0 = Release|Any CPU + {4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.Signed|Any CPU.ActiveCfg = Release|Any CPU + {4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.Signed|Any CPU.Build.0 = Release|Any CPU + {4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.Signed|x86.ActiveCfg = Release|Any CPU + {4F26D5D8-A7B0-42B3-BA42-7CB7D245934E}.Signed|x86.Build.0 = Release|Any CPU + {680A1709-25EB-4D52-A87F-EE03FFD94BAA}.AppStore|Any CPU.ActiveCfg = Signed|Any CPU + {680A1709-25EB-4D52-A87F-EE03FFD94BAA}.AppStore|Any CPU.Build.0 = Signed|Any CPU + {680A1709-25EB-4D52-A87F-EE03FFD94BAA}.AppStore|x86.ActiveCfg = Signed|Any CPU + {680A1709-25EB-4D52-A87F-EE03FFD94BAA}.AppStore|x86.Build.0 = Signed|Any CPU + {680A1709-25EB-4D52-A87F-EE03FFD94BAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {680A1709-25EB-4D52-A87F-EE03FFD94BAA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {680A1709-25EB-4D52-A87F-EE03FFD94BAA}.Debug|x86.ActiveCfg = Debug|Any CPU + {680A1709-25EB-4D52-A87F-EE03FFD94BAA}.Debug|x86.Build.0 = Debug|Any CPU + {680A1709-25EB-4D52-A87F-EE03FFD94BAA}.Release Mono|Any CPU.ActiveCfg = Release|Any CPU + {680A1709-25EB-4D52-A87F-EE03FFD94BAA}.Release Mono|Any CPU.Build.0 = Release|Any CPU + {680A1709-25EB-4D52-A87F-EE03FFD94BAA}.Release Mono|x86.ActiveCfg = Release|Any CPU + {680A1709-25EB-4D52-A87F-EE03FFD94BAA}.Release Mono|x86.Build.0 = Release|Any CPU + {680A1709-25EB-4D52-A87F-EE03FFD94BAA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {680A1709-25EB-4D52-A87F-EE03FFD94BAA}.Release|Any CPU.Build.0 = Release|Any CPU + {680A1709-25EB-4D52-A87F-EE03FFD94BAA}.Release|x86.ActiveCfg = Release|Any CPU + {680A1709-25EB-4D52-A87F-EE03FFD94BAA}.Release|x86.Build.0 = Release|Any CPU + {680A1709-25EB-4D52-A87F-EE03FFD94BAA}.Signed|Any CPU.ActiveCfg = Signed|Any CPU + {680A1709-25EB-4D52-A87F-EE03FFD94BAA}.Signed|Any CPU.Build.0 = Signed|Any CPU + {680A1709-25EB-4D52-A87F-EE03FFD94BAA}.Signed|x86.ActiveCfg = Signed|Any CPU + {680A1709-25EB-4D52-A87F-EE03FFD94BAA}.Signed|x86.Build.0 = Signed|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution Policies = $0 From 1ccabf572111232801d47983d4125519bfbb1f30 Mon Sep 17 00:00:00 2001 From: Luke Date: Sun, 13 Nov 2016 23:01:03 -0500 Subject: [PATCH 06/15] update mac project --- .../Emby.Server.Mac.csproj | 165 +----------------- MediaBrowser.Server.Mac/MacAppHost.cs | 10 ++ MediaBrowser.Server.Mac/Native/NativeApp.cs | 46 ----- .../Native/NetworkManager.cs | 50 ------ 4 files changed, 12 insertions(+), 259 deletions(-) create mode 100644 MediaBrowser.Server.Mac/MacAppHost.cs delete mode 100644 MediaBrowser.Server.Mac/Native/NativeApp.cs delete mode 100644 MediaBrowser.Server.Mac/Native/NetworkManager.cs diff --git a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj index 6995a5bec..56c7caad4 100644 --- a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj +++ b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj @@ -104,7 +104,6 @@ - @@ -115,69 +114,17 @@ AppController.cs - - SharedVersion.cs - - Native\CertificateGenerator.cs - - + Native\SqliteExtensions.cs - - Security\ASN1.cs - - - Security\ASN1Convert.cs - - - Security\BitConverterLE.cs - - - Security\CryptoConvert.cs - - - Security\PKCS1.cs - - - Security\PKCS12.cs - - - Security\PKCS7.cs - - - Security\PKCS8.cs - - - Security\X501Name.cs - - - Security\X509Builder.cs - - - Security\X509Certificate.cs - - - Security\X509CertificateBuilder.cs - - - Security\X509CertificateCollection.cs - - - Security\X509Extension.cs - - - Security\X509Extensions.cs - - - Security\X520Attributes.cs - + @@ -264,114 +211,6 @@ - - Resources\swagger-ui\index.html - - - Resources\swagger-ui\o2c.html - - - Resources\swagger-ui\patch.js - - - Resources\swagger-ui\swagger-ui.js - - - Resources\swagger-ui\swagger-ui.min.js - - - Resources\swagger-ui\css\reset.css - - - Resources\swagger-ui\css\screen.css - - - Resources\swagger-ui\css\typography.css - - - Resources\swagger-ui\fonts\droid-sans-v6-latin-700.eot - - - Resources\swagger-ui\fonts\droid-sans-v6-latin-700.svg - - - Resources\swagger-ui\fonts\droid-sans-v6-latin-700.ttf - - - Resources\swagger-ui\fonts\droid-sans-v6-latin-700.woff - - - Resources\swagger-ui\fonts\droid-sans-v6-latin-700.woff2 - - - Resources\swagger-ui\fonts\droid-sans-v6-latin-regular.eot - - - Resources\swagger-ui\fonts\droid-sans-v6-latin-regular.svg - - - Resources\swagger-ui\fonts\droid-sans-v6-latin-regular.ttf - - - Resources\swagger-ui\fonts\droid-sans-v6-latin-regular.woff - - - Resources\swagger-ui\fonts\droid-sans-v6-latin-regular.woff2 - - - Resources\swagger-ui\images\explorer_icons.png - - - Resources\swagger-ui\images\logo_small.png - - - Resources\swagger-ui\images\pet_store_api.png - - - Resources\swagger-ui\images\throbber.gif - - - Resources\swagger-ui\images\wordnik_api.png - - - Resources\swagger-ui\lib\backbone-min.js - - - Resources\swagger-ui\lib\handlebars-2.0.0.js - - - Resources\swagger-ui\lib\highlight.7.3.pack.js - - - Resources\swagger-ui\lib\jquery-1.8.0.min.js - - - Resources\swagger-ui\lib\jquery.ba-bbq.min.js - - - Resources\swagger-ui\lib\jquery.slideto.min.js - - - Resources\swagger-ui\lib\jquery.wiggle.min.js - - - Resources\swagger-ui\lib\marked.js - - - Resources\swagger-ui\lib\shred.bundle.js - - - Resources\swagger-ui\lib\swagger-client.js - - - Resources\swagger-ui\lib\swagger-oauth.js - - - Resources\swagger-ui\lib\underscore-min.js - - - Resources\swagger-ui\lib\shred\content.js - Resources\dashboard-ui\about.html diff --git a/MediaBrowser.Server.Mac/MacAppHost.cs b/MediaBrowser.Server.Mac/MacAppHost.cs new file mode 100644 index 000000000..352cd34bb --- /dev/null +++ b/MediaBrowser.Server.Mac/MacAppHost.cs @@ -0,0 +1,10 @@ +using System; +namespace MediaBrowser.Server.Mac +{ + public class MacAppHost + { + public MacAppHost() + { + } + } +} diff --git a/MediaBrowser.Server.Mac/Native/NativeApp.cs b/MediaBrowser.Server.Mac/Native/NativeApp.cs deleted file mode 100644 index 59fa92dd1..000000000 --- a/MediaBrowser.Server.Mac/Native/NativeApp.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using MediaBrowser.Server.Startup.Common; -using MediaBrowser.Model.Logging; - -namespace MediaBrowser.Server.Mac -{ - /// - /// Class NativeApp - /// - public class NativeApp : BaseMonoApp - { - public NativeApp(ILogger logger) - : base(logger) - { - } - - /// - /// Shutdowns this instance. - /// - public override void Shutdown() - { - MainClass.Shutdown(); - } - - /// - /// Determines whether this instance [can self restart]. - /// - /// true if this instance can self restart; otherwise, false. - public override bool CanSelfRestart - { - get - { - return true; - } - } - - /// - /// Restarts this instance. - /// - public override void Restart(StartupOptions options) - { - MainClass.Restart(); - } - } -} - diff --git a/MediaBrowser.Server.Mac/Native/NetworkManager.cs b/MediaBrowser.Server.Mac/Native/NetworkManager.cs deleted file mode 100644 index 959ac6774..000000000 --- a/MediaBrowser.Server.Mac/Native/NetworkManager.cs +++ /dev/null @@ -1,50 +0,0 @@ -using MediaBrowser.Common.Implementations.Networking; -using MediaBrowser.Common.Net; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Net; -using System.Collections.Generic; -using MediaBrowser.Server.Mono.Networking; - -namespace MediaBrowser.Server.Mac -{ - /// - /// Class NetUtils - /// - public class NetworkManager : BaseNetworkManager, INetworkManager - { - public NetworkManager(ILogger logger) - : base(logger) - { - } - - /// - /// Gets the network shares. - /// - /// The path. - /// IEnumerable{NetworkShare}. - public IEnumerable GetNetworkShares(string path) - { - return new List (); - } - - /// - /// Gets available devices within the domain - /// - /// PC's in the Domain - public IEnumerable GetNetworkDevices() - { - return new List (); - } - - /// - /// Generates a self signed certificate at the locatation specified by . - /// - /// The path to generate the certificate. - /// The common name for the certificate. - public void GenerateSelfSignedSslCertificate(string certificatePath, string hostname) - { - CertificateGenerator.CreateSelfSignCertificatePfx(certificatePath, hostname, Logger); - } - } -} From db5008644b7ddd09166b91635040a2c82908b0dc Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Sun, 13 Nov 2016 23:08:26 -0500 Subject: [PATCH 07/15] update mac project --- MediaBrowser.Server.Mac/MacAppHost.cs | 153 +++++++++++++++++++++++++- 1 file changed, 149 insertions(+), 4 deletions(-) diff --git a/MediaBrowser.Server.Mac/MacAppHost.cs b/MediaBrowser.Server.Mac/MacAppHost.cs index 352cd34bb..c909b3e0f 100644 --- a/MediaBrowser.Server.Mac/MacAppHost.cs +++ b/MediaBrowser.Server.Mac/MacAppHost.cs @@ -1,10 +1,155 @@ using System; +using System.Collections.Generic; +using System.Reflection; +using Emby.Server.Core; +using Emby.Server.Core.Data; +using Emby.Server.Core.FFMpeg; +using MediaBrowser.IsoMounter; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.System; +using MediaBrowser.Server.Mono.Native; +using System.Diagnostics; + namespace MediaBrowser.Server.Mac { public class MacAppHost { - public MacAppHost() - { - } - } + public MacAppHost(ServerApplicationPaths applicationPaths, ILogManager logManager, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, IMemoryStreamFactory memoryStreamFactory, MediaBrowser.Common.Net.INetworkManager networkManager, Action certificateGenerator, Func defaultUsernameFactory) : base(applicationPaths, logManager, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, memoryStreamFactory, networkManager, certificateGenerator, defaultUsernameFactory) + { + } + + public override bool CanSelfRestart + { + get + { + return false; + } + } + + public override bool CanSelfUpdate + { + get + { + return false; + } + } + + protected override FFMpegInstallInfo GetFfmpegInstallInfo() + { + var info = new FFMpegInstallInfo(); + + info.ArchiveType = "7z"; + + switch (EnvironmentInfo.SystemArchitecture) + { + case Architecture.X64: + info.Version = "20160124"; + break; + case Architecture.X86: + info.Version = "20150110"; + break; + } + + info.DownloadUrls = GetDownloadUrls(environment); + + return info; + } + + private static string[] GetDownloadUrls(NativeEnvironment environment) + { + switch (EnvironmentInfo.SystemArchitecture) + { + case Architecture.X64: + return new[] + { + "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/osx/ffmpeg-x64-2.8.5.7z" + }; + } + + // No version available + return new string[] { }; + } + + protected override void RestartInternal() + { + MainClass.Restart(StartupOptions); + } + + protected override List GetAssembliesWithPartsInternal() + { + var list = new List(); + + list.Add(GetType().Assembly); + + return list; + } + + protected override void ShutdownInternal() + { + MainClass.Shutdown(); + } + + protected override void AuthorizeServer() + { + throw new NotImplementedException(); + } + + protected override IDbConnector GetDbConnector() + { + return new DbConnector(Logger); + } + + protected override void ConfigureAutoRunInternal(bool autorun) + { + throw new NotImplementedException(); + } + + public override void LaunchUrl(string url) + { + var process = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = url + }, + + EnableRaisingEvents = true, + }; + + process.Exited += ProcessExited; + + process.Start(); + } + + private static void ProcessExited(object sender, EventArgs e) + { + ((Process)sender).Dispose(); + } + + protected override void EnableLoopbackInternal(string appName) + { + } + + public override bool SupportsRunningAsService + { + get + { + return false; + } + } + + public override bool SupportsAutoRunAtStartup + { + get { return false; } + } + + public override bool IsRunningAsService + { + get + { + return false; + } + } + } } From 9700a3be600e569d6f5c036f79aee8b39431696d Mon Sep 17 00:00:00 2001 From: Luke Date: Sun, 13 Nov 2016 23:50:23 -0500 Subject: [PATCH 08/15] update mac project --- MediaBrowser.Server.Mac/AppController.cs | 2 - .../Emby.Server.Mac.csproj | 73 ++++- MediaBrowser.Server.Mac/MacAppHost.cs | 5 +- MediaBrowser.Server.Mac/Main.cs | 33 ++- MediaBrowser.Server.Mac/MenuBarIcon.cs | 3 +- MediaBrowser.Server.Mac/Native/BaseMonoApp.cs | 272 ------------------ MediaBrowser.Server.Mac/Native/DbConnector.cs | 2 +- .../Native/MonoFileSystem.cs | 21 ++ .../Native/PowerManagement.cs | 15 + 9 files changed, 116 insertions(+), 310 deletions(-) delete mode 100644 MediaBrowser.Server.Mac/Native/BaseMonoApp.cs create mode 100644 MediaBrowser.Server.Mac/Native/MonoFileSystem.cs create mode 100644 MediaBrowser.Server.Mac/Native/PowerManagement.cs diff --git a/MediaBrowser.Server.Mac/AppController.cs b/MediaBrowser.Server.Mac/AppController.cs index 8d690b813..9e32b53f1 100644 --- a/MediaBrowser.Server.Mac/AppController.cs +++ b/MediaBrowser.Server.Mac/AppController.cs @@ -1,8 +1,6 @@ using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Localization; using MediaBrowser.Model.Logging; -using MediaBrowser.Server.Startup.Common.Browser; using System; using MonoMac.Foundation; using MonoMac.AppKit; diff --git a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj index 56c7caad4..7f6c02855 100644 --- a/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj +++ b/MediaBrowser.Server.Mac/Emby.Server.Mac.csproj @@ -90,16 +90,22 @@ ..\packages\Mono.Posix.4.0.0.0\lib\net40\Mono.Posix.dll - - ..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll - - - ..\packages\CommonIO.1.0.0.9\lib\net45\CommonIO.dll - ..\ThirdParty\System.Data.SQLite.ManagedOnly\1.0.94.0\System.Data.SQLite.dll + + ..\ThirdParty\emby\Emby.Common.Implementations.dll + + + ..\ThirdParty\emby\Emby.Server.Core.dll + + + ..\ThirdParty\emby\Mono.Nat.dll + + + ..\ThirdParty\taglib\TagLib.Portable.dll + @@ -114,7 +120,6 @@ AppController.cs - SharedVersion.cs @@ -125,6 +130,8 @@ Native\SqliteExtensions.cs + + @@ -154,18 +161,10 @@ {9142EEFA-7570-41E1-BFCC-468BB571AF2F} MediaBrowser.Common - - {C4D2573A-3FD3-441F-81AF-174AC4CD4E1D} - MediaBrowser.Common.Implementations - {2E781478-814D-4A48-9D80-BFF206441A65} MediaBrowser.Server.Implementations - - {734098EB-6DC1-4DD0-A1CA-3140DCD2737C} - MediaBrowser.Dlna - {7EF9F3E0-697D-42F3-A08F-19DEB5F84392} MediaBrowser.LocalMetadata @@ -194,6 +193,50 @@ {4FD51AC5-2C16-4308-A993-C3A84F3B4582} MediaBrowser.Api + + {E383961B-9356-4D5D-8233-9A1079D03055} + Emby.Server.Implementations + + + {89AB4548-770D-41FD-A891-8DAFF44F452C} + Emby.Photos + + + {C97A239E-A96C-4D64-A844-CCF8CC30AECB} + Emby.Drawing.Net + + + {6CFEE013-6E7C-432B-AC37-CABF0880C69A} + Emby.Drawing.ImageMagick + + + {08FFF49B-F175-4807-A2B5-73B0EBD9F716} + Emby.Drawing + + + {805844AB-E92F-45E6-9D99-4F6D48D129A5} + Emby.Dlna + + + {713F42B5-878E-499D-A878-E4C652B1D5E8} + DvdLib + + + {88AE38DF-19D7-406F-A6A9-09527719A21E} + BDInfo + + + {4F26D5D8-A7B0-42B3-BA42-7CB7D245934E} + SocketHttpListener.Portable + + + {680A1709-25EB-4D52-A87F-EE03FFD94BAA} + ServiceStack + + + {21002819-C39A-4D3E-BE83-2A276A77FB1F} + RSSDP + diff --git a/MediaBrowser.Server.Mac/MacAppHost.cs b/MediaBrowser.Server.Mac/MacAppHost.cs index c909b3e0f..660f6913d 100644 --- a/MediaBrowser.Server.Mac/MacAppHost.cs +++ b/MediaBrowser.Server.Mac/MacAppHost.cs @@ -4,7 +4,6 @@ using System.Reflection; using Emby.Server.Core; using Emby.Server.Core.Data; using Emby.Server.Core.FFMpeg; -using MediaBrowser.IsoMounter; using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; using MediaBrowser.Model.System; @@ -13,7 +12,7 @@ using System.Diagnostics; namespace MediaBrowser.Server.Mac { - public class MacAppHost + public class MacAppHost : ApplicationHost { public MacAppHost(ServerApplicationPaths applicationPaths, ILogManager logManager, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, IMemoryStreamFactory memoryStreamFactory, MediaBrowser.Common.Net.INetworkManager networkManager, Action certificateGenerator, Func defaultUsernameFactory) : base(applicationPaths, logManager, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, memoryStreamFactory, networkManager, certificateGenerator, defaultUsernameFactory) { @@ -56,7 +55,7 @@ namespace MediaBrowser.Server.Mac return info; } - private static string[] GetDownloadUrls(NativeEnvironment environment) + private string[] GetDownloadUrls() { switch (EnvironmentInfo.SystemArchitecture) { diff --git a/MediaBrowser.Server.Mac/Main.cs b/MediaBrowser.Server.Mac/Main.cs index b48f44707..d0d489142 100644 --- a/MediaBrowser.Server.Mac/Main.cs +++ b/MediaBrowser.Server.Mac/Main.cs @@ -10,25 +10,22 @@ using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Implementations.IO; -using MediaBrowser.Common.Implementations.Logging; using MediaBrowser.Model.Logging; using MediaBrowser.Server.Implementations; using MediaBrowser.Server.Startup.Common; -using MediaBrowser.Server.Startup.Common.Browser; using Microsoft.Win32; using MonoMac.AppKit; using MonoMac.Foundation; using MonoMac.ObjCRuntime; -using CommonIO; -using MediaBrowser.Server.Implementations.Logging; +using Emby.Server.Core; +using Emby.Common.Implementations.Logging; +using Emby.Server.Mac.Native; namespace MediaBrowser.Server.Mac { class MainClass { - internal static ApplicationHost AppHost; + internal static MacAppHost AppHost; private static ILogger _logger; @@ -41,7 +38,9 @@ namespace MediaBrowser.Server.Mac // Allow this to be specified on the command line. var customProgramDataPath = options.GetOption("-programdata"); - var appPaths = CreateApplicationPaths(applicationPath, customProgramDataPath); + var appFolderPath = Path.GetDirectoryName(applicationPath); + + var appPaths = CreateApplicationPaths(appFolderPath, customProgramDataPath); var logManager = new NlogManager(appPaths.LogDirectoryPath, "server"); logManager.ReloadLogger(LogSeverity.Info); @@ -58,7 +57,7 @@ namespace MediaBrowser.Server.Mac NSApplication.Main (args); } - private static ServerApplicationPaths CreateApplicationPaths(string applicationPath, string programDataPath) + private static ServerApplicationPaths CreateApplicationPaths(string appFolderPath, string programDataPath) { if (string.IsNullOrEmpty(programDataPath)) { @@ -71,9 +70,9 @@ namespace MediaBrowser.Server.Mac } // Within the mac bundle, go uo two levels then down into Resources folder - var resourcesPath = Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName (applicationPath)), "Resources"); + var resourcesPath = Path.Combine(Path.GetDirectoryName(appFolderPath), "Resources"); - return new ServerApplicationPaths(programDataPath, applicationPath, resourcesPath); + return new ServerApplicationPaths(programDataPath, appFolderPath, resourcesPath); } /// @@ -91,12 +90,16 @@ namespace MediaBrowser.Server.Mac // Allow all https requests ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; }); - var fileSystem = new ManagedFileSystem(new PatternsLogger(logManager.GetLogger("FileSystem")), false, true); + var fileSystem = new MonoFileSystem(logManager.GetLogger("FileSystem"), false, false); fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem)); - var nativeApp = new NativeApp(logManager.GetLogger("App")); - - AppHost = new ApplicationHost(appPaths, logManager, options, fileSystem, "Emby.Server.Mac.pkg", nativeApp); + AppHost = new MacAppHost(appPaths, + logManager, + options, + fileSystem, + new PowerManagement(), + "Emby.Server.Mac.pkg", + nativeApp); if (options.ContainsOption("-v")) { Console.WriteLine (AppHost.ApplicationVersion.ToString()); diff --git a/MediaBrowser.Server.Mac/MenuBarIcon.cs b/MediaBrowser.Server.Mac/MenuBarIcon.cs index 865f45057..646b5ff69 100644 --- a/MediaBrowser.Server.Mac/MenuBarIcon.cs +++ b/MediaBrowser.Server.Mac/MenuBarIcon.cs @@ -1,11 +1,10 @@ using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Localization; using MediaBrowser.Model.Logging; -using MediaBrowser.Server.Startup.Common.Browser; using System; using MonoMac.Foundation; using MonoMac.AppKit; +using Emby.Server.Core.Browser; namespace MediaBrowser.Server.Mac { diff --git a/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs b/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs deleted file mode 100644 index f28ff8c0d..000000000 --- a/MediaBrowser.Server.Mac/Native/BaseMonoApp.cs +++ /dev/null @@ -1,272 +0,0 @@ -using MediaBrowser.Common.Net; -using MediaBrowser.Model.Logging; -using MediaBrowser.Server.Startup.Common; -using Mono.Unix.Native; -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text.RegularExpressions; -using MediaBrowser.Server.Implementations.Persistence; -using MediaBrowser.Server.Startup.Common.FFMpeg; -using System.Diagnostics; -using MediaBrowser.Model.System; - -namespace MediaBrowser.Server.Mac -{ - public abstract class BaseMonoApp : INativeApp - { - protected ILogger Logger { get; private set; } - - protected BaseMonoApp(ILogger logger) - { - Logger = logger; - } - - /// - /// Shutdowns this instance. - /// - public abstract void Shutdown(); - - /// - /// Restarts this instance. - /// - public virtual void Restart(StartupOptions options) - { - throw new NotImplementedException(); - } - - /// - /// Determines whether this instance [can self restart]. - /// - /// true if this instance [can self restart]; otherwise, false. - public virtual bool CanSelfRestart - { - get - { - return false; - } - } - - public void PreventSystemStandby() - { - - } - - public void AllowSystemStandby() - { - - } - - public IDbConnector GetDbConnector() - { - return new DbConnector(Logger); - } - - public virtual bool SupportsLibraryMonitor - { - get - { - return true; - } - } - - /// - /// Gets a value indicating whether this instance can self update. - /// - /// true if this instance can self update; otherwise, false. - public bool CanSelfUpdate - { - get - { - return false; - } - } - - public bool SupportsAutoRunAtStartup - { - get { return false; } - } - - public List GetAssembliesWithParts() - { - var list = new List(); - - list.Add(GetType().Assembly); - - return list; - } - - public void AuthorizeServer(int udpPort, int httpServerPort, int httpsPort, string applicationPath, string tempDirectory) - { - } - - private NativeEnvironment _nativeEnvironment; - public NativeEnvironment Environment - { - get { return _nativeEnvironment ?? (_nativeEnvironment = GetEnvironmentInfo()); } - } - - public bool SupportsRunningAsService - { - get - { - return false; - } - } - - public bool IsRunningAsService - { - get - { - return false; - } - } - - public void ConfigureAutoRun(bool autorun) - { - } - - public void LaunchUrl(string url) - { - var process = new Process - { - StartInfo = new ProcessStartInfo - { - FileName = url - }, - - EnableRaisingEvents = true, - }; - - process.Exited += ProcessExited; - - process.Start(); - } - - /// - /// Processes the exited. - /// - /// The sender. - /// The instance containing the event data. - private static void ProcessExited(object sender, EventArgs e) - { - ((Process)sender).Dispose(); - } - - public FFMpegInstallInfo GetFfmpegInstallInfo() - { - return GetInfo(Environment); - } - - public static FFMpegInstallInfo GetInfo(NativeEnvironment environment) - { - var info = new FFMpegInstallInfo(); - - info.ArchiveType = "7z"; - - switch (environment.SystemArchitecture) - { - case Architecture.X64: - info.Version = "20160124"; - break; - case Architecture.X86: - info.Version = "20150110"; - break; - } - - info.DownloadUrls = GetDownloadUrls(environment); - - return info; - } - - private static string[] GetDownloadUrls(NativeEnvironment environment) - { - switch (environment.SystemArchitecture) - { - case Architecture.X64: - return new[] - { - "https://github.com/MediaBrowser/Emby.Resources/raw/master/ffmpeg/osx/ffmpeg-x64-2.8.5.7z" - }; - } - - // No version available - return new string[] { }; - } - - public INetworkManager CreateNetworkManager(ILogger logger) - { - return new NetworkManager(logger); - } - - public void EnableLoopback(string appName) - { - - } - - public bool PortsRequireAuthorization(string applicationPath) - { - return false; - } - - private NativeEnvironment GetEnvironmentInfo() - { - var info = new NativeEnvironment - { - OperatingSystem = Startup.Common.OperatingSystem.Linux - }; - - var uname = GetUnixName(); - - var sysName = uname.sysname ?? string.Empty; - - info.OperatingSystem = Startup.Common.OperatingSystem.Osx; - - var archX86 = new Regex("(i|I)[3-6]86"); - - if (archX86.IsMatch(uname.machine)) - { - info.SystemArchitecture = Architecture.X86; - } - else if (string.Equals(uname.machine, "x86_64", StringComparison.OrdinalIgnoreCase)) - { - info.SystemArchitecture = Architecture.X64; - } - else if (uname.machine.StartsWith("arm", StringComparison.OrdinalIgnoreCase)) - { - info.SystemArchitecture = Architecture.Arm; - } - - info.OperatingSystemVersionString = string.IsNullOrWhiteSpace(sysName) ? - System.Environment.OSVersion.VersionString : - sysName; - - return info; - } - - private Uname _unixName; - private Uname GetUnixName() - { - if (_unixName == null) - { - var uname = new Uname(); - Utsname utsname; - var callResult = Syscall.uname(out utsname); - if (callResult == 0) - { - uname.sysname = utsname.sysname; - uname.machine = utsname.machine; - } - - _unixName = uname; - } - return _unixName; - } - - private class Uname - { - public string sysname = string.Empty; - public string machine = string.Empty; - } - } -} diff --git a/MediaBrowser.Server.Mac/Native/DbConnector.cs b/MediaBrowser.Server.Mac/Native/DbConnector.cs index 4c19210b8..1ef9d2388 100644 --- a/MediaBrowser.Server.Mac/Native/DbConnector.cs +++ b/MediaBrowser.Server.Mac/Native/DbConnector.cs @@ -3,7 +3,7 @@ using System.Data; using System.Data.SQLite; using System.Threading.Tasks; using MediaBrowser.Model.Logging; -using MediaBrowser.Server.Implementations.Persistence; +using Emby.Server.Core.Data; namespace MediaBrowser.Server.Mac { diff --git a/MediaBrowser.Server.Mac/Native/MonoFileSystem.cs b/MediaBrowser.Server.Mac/Native/MonoFileSystem.cs new file mode 100644 index 000000000..e71345723 --- /dev/null +++ b/MediaBrowser.Server.Mac/Native/MonoFileSystem.cs @@ -0,0 +1,21 @@ +using Emby.Common.Implementations.IO; +using MediaBrowser.Model.Logging; +using Mono.Unix.Native; + +namespace Emby.Server.Mac.Native +{ + public class MonoFileSystem : ManagedFileSystem + { + public MonoFileSystem(ILogger logger, bool supportsAsyncFileStreams, bool enableManagedInvalidFileNameChars) : base(logger, supportsAsyncFileStreams, enableManagedInvalidFileNameChars, false) + { + } + + public override void SetExecutable(string path) + { + // Linux: File permission to 666, and user's execute bit + Logger.Info("Syscall.chmod {0} FilePermissions.DEFFILEMODE | FilePermissions.S_IRWXU | FilePermissions.S_IXGRP | FilePermissions.S_IXOTH", path); + + Syscall.chmod(path, FilePermissions.DEFFILEMODE | FilePermissions.S_IRWXU | FilePermissions.S_IXGRP | FilePermissions.S_IXOTH); + } + } +} diff --git a/MediaBrowser.Server.Mac/Native/PowerManagement.cs b/MediaBrowser.Server.Mac/Native/PowerManagement.cs new file mode 100644 index 000000000..f3c97d658 --- /dev/null +++ b/MediaBrowser.Server.Mac/Native/PowerManagement.cs @@ -0,0 +1,15 @@ +using MediaBrowser.Model.System; + +namespace Emby.Server.Mac.Native +{ + public class PowerManagement : IPowerManagement + { + public void PreventSystemStandby() + { + } + + public void AllowSystemStandby() + { + } + } +} From 9fb11f1a5692344715dfd6bc09410e3baf7e3fe1 Mon Sep 17 00:00:00 2001 From: Luke Date: Mon, 14 Nov 2016 00:41:57 -0500 Subject: [PATCH 09/15] update mac project --- MediaBrowser.Server.Mac/MacAppHost.cs | 2 +- MediaBrowser.Server.Mac/Main.cs | 50 ++++++++++++++------------- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/MediaBrowser.Server.Mac/MacAppHost.cs b/MediaBrowser.Server.Mac/MacAppHost.cs index 660f6913d..9e068acd4 100644 --- a/MediaBrowser.Server.Mac/MacAppHost.cs +++ b/MediaBrowser.Server.Mac/MacAppHost.cs @@ -7,7 +7,7 @@ using Emby.Server.Core.FFMpeg; using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; using MediaBrowser.Model.System; -using MediaBrowser.Server.Mono.Native; +using Emby.Server.Mac.Native; using System.Diagnostics; namespace MediaBrowser.Server.Mac diff --git a/MediaBrowser.Server.Mac/Main.cs b/MediaBrowser.Server.Mac/Main.cs index d0d489142..9d646547e 100644 --- a/MediaBrowser.Server.Mac/Main.cs +++ b/MediaBrowser.Server.Mac/Main.cs @@ -12,14 +12,16 @@ using System.Threading; using System.Threading.Tasks; using MediaBrowser.Model.Logging; using MediaBrowser.Server.Implementations; -using MediaBrowser.Server.Startup.Common; -using Microsoft.Win32; using MonoMac.AppKit; using MonoMac.Foundation; using MonoMac.ObjCRuntime; using Emby.Server.Core; using Emby.Common.Implementations.Logging; using Emby.Server.Mac.Native; +using Emby.Server.Implementations.IO; +using Emby.Common.Implementations.Networking; +using MediaBrowser.Server.Startup.Common; +using MediaBrowser.Server.Startup.Common.IO; namespace MediaBrowser.Server.Mac { @@ -85,21 +87,34 @@ namespace MediaBrowser.Server.Mac ILogManager logManager, StartupOptions options) { - SystemEvents.SessionEnding += SystemEvents_SessionEnding; - // Allow all https requests ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; }); var fileSystem = new MonoFileSystem(logManager.GetLogger("FileSystem"), false, false); fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem)); - AppHost = new MacAppHost(appPaths, - logManager, - options, - fileSystem, - new PowerManagement(), - "Emby.Server.Mac.pkg", - nativeApp); + var environmentInfo = GetEnvironmentInfo(); + + var imageEncoder = ImageEncoderHelper.GetImageEncoder(_logger, + logManager, + fileSystem, + options, + () => AppHost.HttpClient, + appPaths); + + AppHost = new MacAppHost(appPaths, + logManager, + options, + fileSystem, + new PowerManagement(), + "Emby.Server.Mac.pkg", + environmentInfo, + imageEncoder, + new Startup.Common.SystemEvents(logManager.GetLogger("SystemEvents")), + new MemoryStreamProvider(), + new NetworkManager(logManager.GetLogger("NetworkManager")), + GenerateCertificate, + () => Environment.UserName); if (options.ContainsOption("-v")) { Console.WriteLine (AppHost.ApplicationVersion.ToString()); @@ -125,19 +140,6 @@ namespace MediaBrowser.Server.Mac } } - /// - /// Handles the SessionEnding event of the SystemEvents control. - /// - /// The source of the event. - /// The instance containing the event data. - static void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e) - { - if (e.Reason == SessionEndReasons.SystemShutdown) - { - Shutdown(); - } - } - public static void Shutdown() { ShutdownApp(); From 04a71e3a31a5c26a3d0c80d5f463071403239cad Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 14 Nov 2016 00:45:13 -0500 Subject: [PATCH 10/15] update mac project --- MediaBrowser.Server.Mac/Main.cs | 109 +++++++++++++++++++++++++++++--- 1 file changed, 100 insertions(+), 9 deletions(-) diff --git a/MediaBrowser.Server.Mac/Main.cs b/MediaBrowser.Server.Mac/Main.cs index 9d646547e..5aa6d9eea 100644 --- a/MediaBrowser.Server.Mac/Main.cs +++ b/MediaBrowser.Server.Mac/Main.cs @@ -1,17 +1,22 @@ -using System; +using MediaBrowser.Model.Logging; +using MediaBrowser.Server.Mono.Native; +using MediaBrowser.Server.Startup.Common; +using MediaBrowser.Server.Startup.Common.IO; +using MediaBrowser.Server.Implementations; +using System; using System.Diagnostics; -using System.Drawing; +using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Net.Security; using System.Reflection; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Drawing; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Model.Logging; -using MediaBrowser.Server.Implementations; using MonoMac.AppKit; using MonoMac.Foundation; using MonoMac.ObjCRuntime; @@ -20,8 +25,8 @@ using Emby.Common.Implementations.Logging; using Emby.Server.Mac.Native; using Emby.Server.Implementations.IO; using Emby.Common.Implementations.Networking; -using MediaBrowser.Server.Startup.Common; -using MediaBrowser.Server.Startup.Common.IO; +using Emby.Common.Implementations.Security; +using Mono.Unix.Native; namespace MediaBrowser.Server.Mac { @@ -124,9 +129,95 @@ namespace MediaBrowser.Server.Mac Console.WriteLine ("appHost.Init"); Task.Run (() => StartServer(CancellationToken.None)); - } + } - private static async void StartServer(CancellationToken cancellationToken) + private static void GenerateCertificate(string certPath, string certHost) + { + CertificateGenerator.CreateSelfSignCertificatePfx(certPath, certHost, _logger); + } + + private static MonoEnvironmentInfo GetEnvironmentInfo() + { + var info = new MonoEnvironmentInfo(); + + var uname = GetUnixName(); + + var sysName = uname.sysname ?? string.Empty; + + if (string.Equals(sysName, "Darwin", StringComparison.OrdinalIgnoreCase)) + { + //info.OperatingSystem = Startup.Common.OperatingSystem.Osx; + } + else if (string.Equals(sysName, "Linux", StringComparison.OrdinalIgnoreCase)) + { + //info.OperatingSystem = Startup.Common.OperatingSystem.Linux; + } + else if (string.Equals(sysName, "BSD", StringComparison.OrdinalIgnoreCase)) + { + //info.OperatingSystem = Startup.Common.OperatingSystem.Bsd; + info.IsBsd = true; + } + + var archX86 = new Regex("(i|I)[3-6]86"); + + if (archX86.IsMatch(uname.machine)) + { + info.CustomArchitecture = Architecture.X86; + } + else if (string.Equals(uname.machine, "x86_64", StringComparison.OrdinalIgnoreCase)) + { + info.CustomArchitecture = Architecture.X64; + } + else if (uname.machine.StartsWith("arm", StringComparison.OrdinalIgnoreCase)) + { + info.CustomArchitecture = Architecture.Arm; + } + else if (System.Environment.Is64BitOperatingSystem) + { + info.CustomArchitecture = Architecture.X64; + } + else + { + info.CustomArchitecture = Architecture.X86; + } + + return info; + } + + private static Uname _unixName; + + private static Uname GetUnixName() + { + if (_unixName == null) + { + var uname = new Uname(); + try + { + Utsname utsname; + var callResult = Syscall.uname(out utsname); + if (callResult == 0) + { + uname.sysname = utsname.sysname ?? string.Empty; + uname.machine = utsname.machine ?? string.Empty; + } + + } + catch (Exception ex) + { + _logger.ErrorException("Error getting unix name", ex); + } + _unixName = uname; + } + return _unixName; + } + + public class Uname + { + public string sysname = string.Empty; + public string machine = string.Empty; + } + + private static async void StartServer(CancellationToken cancellationToken) { var initProgress = new Progress(); From 33db468646f8772605b02390b764df810989ec8a Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 14 Nov 2016 00:50:27 -0500 Subject: [PATCH 11/15] update mac project --- MediaBrowser.Server.Mac/Main.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Server.Mac/Main.cs b/MediaBrowser.Server.Mac/Main.cs index 5aa6d9eea..b8e000c50 100644 --- a/MediaBrowser.Server.Mac/Main.cs +++ b/MediaBrowser.Server.Mac/Main.cs @@ -302,6 +302,16 @@ namespace MediaBrowser.Server.Mac { return true; } - } + } + + public class MonoEnvironmentInfo : EnvironmentInfo + { + public bool IsBsd { get; set; } + + public virtual string GetUserId() + { + return Syscall.getuid().ToString(CultureInfo.InvariantCulture); + } + } } From ceaf0e2098ecd9aa9ca892142ef1b7d2ed9c26ba Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 14 Nov 2016 00:50:58 -0500 Subject: [PATCH 12/15] update mac project --- MediaBrowser.Server.Mac/Main.cs | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/MediaBrowser.Server.Mac/Main.cs b/MediaBrowser.Server.Mac/Main.cs index b8e000c50..9e7447683 100644 --- a/MediaBrowser.Server.Mac/Main.cs +++ b/MediaBrowser.Server.Mac/Main.cs @@ -136,9 +136,9 @@ namespace MediaBrowser.Server.Mac CertificateGenerator.CreateSelfSignCertificatePfx(certPath, certHost, _logger); } - private static MonoEnvironmentInfo GetEnvironmentInfo() + private static EnvironmentInfo GetEnvironmentInfo() { - var info = new MonoEnvironmentInfo(); + var info = new EnvironmentInfo(); var uname = GetUnixName(); @@ -155,7 +155,7 @@ namespace MediaBrowser.Server.Mac else if (string.Equals(sysName, "BSD", StringComparison.OrdinalIgnoreCase)) { //info.OperatingSystem = Startup.Common.OperatingSystem.Bsd; - info.IsBsd = true; + //info.IsBsd = true; } var archX86 = new Regex("(i|I)[3-6]86"); @@ -303,15 +303,5 @@ namespace MediaBrowser.Server.Mac return true; } } - - public class MonoEnvironmentInfo : EnvironmentInfo - { - public bool IsBsd { get; set; } - - public virtual string GetUserId() - { - return Syscall.getuid().ToString(CultureInfo.InvariantCulture); - } - } } From 6525d64aa8f4fdcea64406386887c9869ebfccdf Mon Sep 17 00:00:00 2001 From: Luke Date: Mon, 14 Nov 2016 01:00:53 -0500 Subject: [PATCH 13/15] update mac project --- MediaBrowser.Server.Mac/MacAppHost.cs | 4 ++-- MediaBrowser.Server.Mac/Main.cs | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/MediaBrowser.Server.Mac/MacAppHost.cs b/MediaBrowser.Server.Mac/MacAppHost.cs index 9e068acd4..054913d4d 100644 --- a/MediaBrowser.Server.Mac/MacAppHost.cs +++ b/MediaBrowser.Server.Mac/MacAppHost.cs @@ -50,7 +50,7 @@ namespace MediaBrowser.Server.Mac break; } - info.DownloadUrls = GetDownloadUrls(environment); + info.DownloadUrls = GetDownloadUrls(); return info; } @@ -72,7 +72,7 @@ namespace MediaBrowser.Server.Mac protected override void RestartInternal() { - MainClass.Restart(StartupOptions); + MainClass.Restart(); } protected override List GetAssembliesWithPartsInternal() diff --git a/MediaBrowser.Server.Mac/Main.cs b/MediaBrowser.Server.Mac/Main.cs index 9e7447683..a3023b82c 100644 --- a/MediaBrowser.Server.Mac/Main.cs +++ b/MediaBrowser.Server.Mac/Main.cs @@ -1,5 +1,4 @@ using MediaBrowser.Model.Logging; -using MediaBrowser.Server.Mono.Native; using MediaBrowser.Server.Startup.Common; using MediaBrowser.Server.Startup.Common.IO; using MediaBrowser.Server.Implementations; @@ -22,11 +21,13 @@ using MonoMac.Foundation; using MonoMac.ObjCRuntime; using Emby.Server.Core; using Emby.Common.Implementations.Logging; +using Emby.Common.Implementations.EnvironmentInfo; using Emby.Server.Mac.Native; using Emby.Server.Implementations.IO; using Emby.Common.Implementations.Networking; using Emby.Common.Implementations.Security; using Mono.Unix.Native; +using MediaBrowser.Model.System; namespace MediaBrowser.Server.Mac { @@ -298,7 +299,10 @@ namespace MediaBrowser.Server.Mac class NoCheckCertificatePolicy : ICertificatePolicy { - public bool CheckValidationResult (ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem) + public bool CheckValidationResult (ServicePoint srvPoint, + System.Security.Cryptography.X509Certificates.X509Certificate certificate, + WebRequest request, + int certificateProblem) { return true; } From 9b5a4c22e33db6d2e4554a61c49d7f6bf3375e24 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 14 Nov 2016 01:44:21 -0500 Subject: [PATCH 14/15] update image & subtitle extraction --- .../Emby.Server.Implementations.csproj | 1 + .../EntryPoints/SystemEvents.cs | 47 ++++++++++++ .../Encoder/MediaEncoder.cs | 72 ++++++------------ .../Subtitles/SubtitleEncoder.cs | 76 ++----------------- MediaBrowser.Model/System/ISystemEvents.cs | 2 + MediaBrowser.Server.Mono/Program.cs | 20 +---- .../SystemEvents.cs | 16 ++++ MediaBrowser.ServerApplication/MainStartup.cs | 14 ---- 8 files changed, 97 insertions(+), 151 deletions(-) create mode 100644 Emby.Server.Implementations/EntryPoints/SystemEvents.cs diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 8f92f062c..13d184b59 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -59,6 +59,7 @@ + diff --git a/Emby.Server.Implementations/EntryPoints/SystemEvents.cs b/Emby.Server.Implementations/EntryPoints/SystemEvents.cs new file mode 100644 index 000000000..021ae47ec --- /dev/null +++ b/Emby.Server.Implementations/EntryPoints/SystemEvents.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MediaBrowser.Model.System; +using MediaBrowser.Controller.Plugins; +using MediaBrowser.Common; + +namespace Emby.Server.Implementations.EntryPoints +{ + public class SystemEvents : IServerEntryPoint + { + private readonly ISystemEvents _systemEvents; + private readonly IApplicationHost _appHost; + + public SystemEvents(ISystemEvents systemEvents, IApplicationHost appHost) + { + _systemEvents = systemEvents; + _appHost = appHost; + } + + public void Run() + { + _systemEvents.SessionLogoff += _systemEvents_SessionLogoff; + _systemEvents.SystemShutdown += _systemEvents_SystemShutdown; + } + + private void _systemEvents_SessionLogoff(object sender, EventArgs e) + { + if (!_appHost.IsRunningAsService) + { + _appHost.Shutdown(); + } + } + + private void _systemEvents_SystemShutdown(object sender, EventArgs e) + { + _appHost.Shutdown(); + } + + public void Dispose() + { + _systemEvents.SystemShutdown -= _systemEvents_SystemShutdown; + } + } +} diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index a52ac0e60..ba1f23dfe 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -542,8 +542,6 @@ namespace MediaBrowser.MediaEncoding.Encoder // Must consume both or ffmpeg may hang due to deadlocks. See comments below. RedirectStandardOutput = true, - //RedirectStandardError = true, - RedirectStandardInput = false, FileName = FFProbePath, Arguments = string.Format(args, probeSizeArgument, inputPath).Trim(), @@ -554,7 +552,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); - using (var processWrapper = new ProcessWrapper(process, this, _logger, false)) + using (var processWrapper = new ProcessWrapper(process, this, _logger)) { await _ffProbeResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); @@ -616,7 +614,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } catch { - StopProcess(processWrapper, 100, true); + StopProcess(processWrapper, 100); throw; } @@ -671,9 +669,7 @@ namespace MediaBrowser.MediaEncoding.Encoder UseShellExecute = false, // Must consume both or ffmpeg may hang due to deadlocks. See comments below. - //RedirectStandardOutput = true, RedirectStandardError = true, - RedirectStandardInput = false, FileName = FFMpegPath, Arguments = string.Format(args, probeSizeArgument, inputPath, videoStream.Index.ToString(CultureInfo.InvariantCulture)).Trim(), @@ -685,7 +681,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); var idetFoundInterlaced = false; - using (var processWrapper = new ProcessWrapper(process, this, _logger, false)) + using (var processWrapper = new ProcessWrapper(process, this, _logger)) { try { @@ -728,7 +724,7 @@ namespace MediaBrowser.MediaEncoding.Encoder } catch { - StopProcess(processWrapper, 100, true); + StopProcess(processWrapper, 100); throw; } @@ -945,7 +941,7 @@ namespace MediaBrowser.MediaEncoding.Encoder _logger.Debug("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); - using (var processWrapper = new ProcessWrapper(process, this, _logger, false)) + using (var processWrapper = new ProcessWrapper(process, this, _logger)) { await resourcePool.WaitAsync(cancellationToken).ConfigureAwait(false); @@ -965,7 +961,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!ranToCompletion) { - StopProcess(processWrapper, 1000, false); + StopProcess(processWrapper, 1000); } } @@ -1043,8 +1039,7 @@ namespace MediaBrowser.MediaEncoding.Encoder FileName = FFMpegPath, Arguments = args, IsHidden = true, - ErrorDialog = false, - RedirectStandardInput = true + ErrorDialog = false }); _logger.Info(process.StartInfo.FileName + " " + process.StartInfo.Arguments); @@ -1053,7 +1048,7 @@ namespace MediaBrowser.MediaEncoding.Encoder bool ranToCompletion = false; - using (var processWrapper = new ProcessWrapper(process, this, _logger, true)) + using (var processWrapper = new ProcessWrapper(process, this, _logger)) { try { @@ -1085,7 +1080,7 @@ namespace MediaBrowser.MediaEncoding.Encoder if (!ranToCompletion) { - StopProcess(processWrapper, 1000, false); + StopProcess(processWrapper, 1000); } } finally @@ -1157,40 +1152,25 @@ namespace MediaBrowser.MediaEncoding.Encoder _runningProcesses.Add(process); } } - private void StopProcess(ProcessWrapper process, int waitTimeMs, bool enableForceKill) + private void StopProcess(ProcessWrapper process, int waitTimeMs) { + try + { + if (process.Process.WaitForExit(waitTimeMs)) + { + return; + } + } + catch (Exception ex) + { + _logger.Error("Error in WaitForExit", ex); + } + try { _logger.Info("Killing ffmpeg process"); - if (process.IsRedirectingStdin) - { - try - { - process.Process.StandardInput.WriteLine("q"); - } - catch (Exception) - { - _logger.Error("Error sending q command to process"); - } - } - - try - { - if (process.Process.WaitForExit(waitTimeMs)) - { - return; - } - } - catch (Exception ex) - { - _logger.Error("Error in WaitForExit", ex); - } - - if (enableForceKill) - { - process.Process.Kill(); - } + process.Process.Kill(); } catch (Exception ex) { @@ -1211,7 +1191,7 @@ namespace MediaBrowser.MediaEncoding.Encoder { if (!process.HasExited) { - StopProcess(process, 500, true); + StopProcess(process, 500); } } } @@ -1252,15 +1232,13 @@ namespace MediaBrowser.MediaEncoding.Encoder public int? ExitCode; private readonly MediaEncoder _mediaEncoder; private readonly ILogger _logger; - public bool IsRedirectingStdin { get; private set; } - public ProcessWrapper(IProcess process, MediaEncoder mediaEncoder, ILogger logger, bool isRedirectingStdin) + public ProcessWrapper(IProcess process, MediaEncoder mediaEncoder, ILogger logger) { Process = process; _mediaEncoder = mediaEncoder; _logger = logger; Process.Exited += Process_Exited; - IsRedirectingStdin = isRedirectingStdin; } void Process_Exited(object sender, EventArgs e) diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 5d065f528..9b31a1012 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -444,10 +444,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles var process = _processFactory.Create(new ProcessOptions { - RedirectStandardOutput = false, - RedirectStandardError = true, - RedirectStandardInput = true, - CreateNoWindow = true, UseShellExecute = false, FileName = _mediaEncoder.EncoderPath, @@ -459,26 +455,16 @@ namespace MediaBrowser.MediaEncoding.Subtitles _logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); - var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "ffmpeg-sub-convert-" + Guid.NewGuid() + ".txt"); - _fileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath)); - - var logFileStream = _fileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, - true); - try { process.Start(); } catch (Exception ex) { - logFileStream.Dispose(); - _logger.ErrorException("Error starting ffmpeg", ex); throw; } - - var logTask = process.StandardError.BaseStream.CopyToAsync(logFileStream); var ranToCompletion = process.WaitForExit(60000); @@ -488,19 +474,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles { _logger.Info("Killing ffmpeg subtitle conversion process"); - process.StandardInput.WriteLine("q"); - process.WaitForExit(1000); - - await logTask.ConfigureAwait(false); + process.Kill(); } catch (Exception ex) { _logger.ErrorException("Error killing subtitle conversion process", ex); } - finally - { - logFileStream.Dispose(); - } } var exitCode = ranToCompletion ? process.ExitCode : -1; @@ -533,13 +512,15 @@ namespace MediaBrowser.MediaEncoding.Subtitles if (failed) { - var msg = string.Format("ffmpeg subtitle converted failed for {0}", inputPath); + var msg = string.Format("ffmpeg subtitle conversion failed for {0}", inputPath); _logger.Error(msg); throw new Exception(msg); } await SetAssFont(outputPath).ConfigureAwait(false); + + _logger.Info("ffmpeg subtitle conversion succeeded for {0}", inputPath); } /// @@ -597,10 +578,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles CreateNoWindow = true, UseShellExecute = false, - RedirectStandardOutput = false, - RedirectStandardError = true, - RedirectStandardInput = true, - FileName = _mediaEncoder.EncoderPath, Arguments = processArgs, IsHidden = true, @@ -609,28 +586,17 @@ namespace MediaBrowser.MediaEncoding.Subtitles _logger.Info("{0} {1}", process.StartInfo.FileName, process.StartInfo.Arguments); - var logFilePath = Path.Combine(_appPaths.LogDirectoryPath, "ffmpeg-sub-extract-" + Guid.NewGuid() + ".txt"); - _fileSystem.CreateDirectory(Path.GetDirectoryName(logFilePath)); - - var logFileStream = _fileSystem.GetFileStream(logFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read, - true); - try { process.Start(); } catch (Exception ex) { - logFileStream.Dispose(); - _logger.ErrorException("Error starting ffmpeg", ex); throw; } - // Important - don't await the log task or we won't be able to kill ffmpeg when the user stops playback - Task.Run(() => StartStreamingLog(process.StandardError.BaseStream, logFileStream)); - var ranToCompletion = process.WaitForExit(300000); if (!ranToCompletion) @@ -639,17 +605,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles { _logger.Info("Killing ffmpeg subtitle extraction process"); - process.StandardInput.WriteLine("q"); - process.WaitForExit(1000); + process.Kill(); } catch (Exception ex) { _logger.ErrorException("Error killing subtitle extraction process", ex); } - finally - { - logFileStream.Dispose(); - } } var exitCode = ranToCompletion ? process.ExitCode : -1; @@ -702,33 +663,6 @@ namespace MediaBrowser.MediaEncoding.Subtitles } } - private async Task StartStreamingLog(Stream source, Stream target) - { - try - { - using (var reader = new StreamReader(source)) - { - while (!reader.EndOfStream) - { - var line = await reader.ReadLineAsync().ConfigureAwait(false); - - var bytes = Encoding.UTF8.GetBytes(Environment.NewLine + line); - - await target.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false); - await target.FlushAsync().ConfigureAwait(false); - } - } - } - catch (ObjectDisposedException) - { - // Don't spam the log. This doesn't seem to throw in windows, but sometimes under linux - } - catch (Exception ex) - { - _logger.ErrorException("Error reading ffmpeg log", ex); - } - } - /// /// Sets the ass font. /// diff --git a/MediaBrowser.Model/System/ISystemEvents.cs b/MediaBrowser.Model/System/ISystemEvents.cs index c50f8ce03..dec8ed8c0 100644 --- a/MediaBrowser.Model/System/ISystemEvents.cs +++ b/MediaBrowser.Model/System/ISystemEvents.cs @@ -6,5 +6,7 @@ namespace MediaBrowser.Model.System { event EventHandler Resume; event EventHandler Suspend; + event EventHandler SessionLogoff; + event EventHandler SystemShutdown; } } diff --git a/MediaBrowser.Server.Mono/Program.cs b/MediaBrowser.Server.Mono/Program.cs index 470525ece..7fc3ff22e 100644 --- a/MediaBrowser.Server.Mono/Program.cs +++ b/MediaBrowser.Server.Mono/Program.cs @@ -1,8 +1,6 @@ using MediaBrowser.Model.Logging; -using MediaBrowser.Server.Implementations; using MediaBrowser.Server.Mono.Native; using MediaBrowser.Server.Startup.Common; -using Microsoft.Win32; using System; using System.Diagnostics; using System.Globalization; @@ -14,7 +12,6 @@ using System.Reflection; using System.Text.RegularExpressions; using System.Threading.Tasks; using Emby.Common.Implementations.EnvironmentInfo; -using Emby.Common.Implementations.IO; using Emby.Common.Implementations.Logging; using Emby.Common.Implementations.Networking; using Emby.Common.Implementations.Security; @@ -84,8 +81,6 @@ namespace MediaBrowser.Server.Mono private static void RunApplication(ServerApplicationPaths appPaths, ILogManager logManager, StartupOptions options) { - Microsoft.Win32.SystemEvents.SessionEnding += SystemEvents_SessionEnding; - // Allow all https requests ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; }); @@ -108,7 +103,7 @@ namespace MediaBrowser.Server.Mono new MemoryStreamProvider(), new NetworkManager(logManager.GetLogger("NetworkManager")), GenerateCertificate, - () => Environment.UserDomainName); + () => Environment.UserName); if (options.ContainsOption("-v")) { @@ -219,19 +214,6 @@ namespace MediaBrowser.Server.Mono public string machine = string.Empty; } - /// - /// Handles the SessionEnding event of the SystemEvents control. - /// - /// The source of the event. - /// The instance containing the event data. - static void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e) - { - if (e.Reason == SessionEndReasons.SystemShutdown) - { - Shutdown(); - } - } - /// /// Handles the UnhandledException event of the CurrentDomain control. /// diff --git a/MediaBrowser.Server.Startup.Common/SystemEvents.cs b/MediaBrowser.Server.Startup.Common/SystemEvents.cs index 088d04a24..8d5cd4ad8 100644 --- a/MediaBrowser.Server.Startup.Common/SystemEvents.cs +++ b/MediaBrowser.Server.Startup.Common/SystemEvents.cs @@ -9,6 +9,8 @@ namespace MediaBrowser.Server.Startup.Common { public event EventHandler Resume; public event EventHandler Suspend; + public event EventHandler SessionLogoff; + public event EventHandler SystemShutdown; private readonly ILogger _logger; @@ -16,6 +18,20 @@ namespace MediaBrowser.Server.Startup.Common { _logger = logger; Microsoft.Win32.SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; + Microsoft.Win32.SystemEvents.SessionEnding += SystemEvents_SessionEnding; + } + + private void SystemEvents_SessionEnding(object sender, Microsoft.Win32.SessionEndingEventArgs e) + { + switch (e.Reason) + { + case Microsoft.Win32.SessionEndReasons.Logoff: + EventHelper.FireEventIfNotNull(SessionLogoff, this, EventArgs.Empty, _logger); + break; + case Microsoft.Win32.SessionEndReasons.SystemShutdown: + EventHelper.FireEventIfNotNull(SystemShutdown, this, EventArgs.Empty, _logger); + break; + } } private void SystemEvents_PowerModeChanged(object sender, Microsoft.Win32.PowerModeChangedEventArgs e) diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index c0ebcde74..f5e768133 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -368,7 +368,6 @@ namespace MediaBrowser.ServerApplication task = InstallVcredist2013IfNeeded(_appHost, _logger); Task.WaitAll(task); - Microsoft.Win32.SystemEvents.SessionEnding += SystemEvents_SessionEnding; Microsoft.Win32.SystemEvents.SessionSwitch += SystemEvents_SessionSwitch; HideSplashScreen(); @@ -569,19 +568,6 @@ namespace MediaBrowser.ServerApplication } } - /// - /// Handles the SessionEnding event of the SystemEvents control. - /// - /// The source of the event. - /// The instance containing the event data. - static void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e) - { - if (e.Reason == SessionEndReasons.SystemShutdown || !IsRunningAsService) - { - Shutdown(); - } - } - /// /// Handles the UnhandledException event of the CurrentDomain control. /// From 43c69713835afee3d27ced041e5f96ec36fa0ce3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 14 Nov 2016 02:28:20 -0500 Subject: [PATCH 15/15] update isavc condition --- .../Playback/BaseStreamingService.cs | 9 ++++++++- MediaBrowser.Api/Playback/StreamRequest.cs | 1 + MediaBrowser.Model/Dlna/StreamBuilder.cs | 18 ++++++++++++++++++ MediaBrowser.Model/Dlna/StreamInfo.cs | 2 ++ 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 690505869..3718edba4 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -1759,6 +1759,13 @@ namespace MediaBrowser.Api.Playback videoRequest.EnableSplittingOnNonKeyFrames = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); } } + else if (i == 30) + { + if (videoRequest != null) + { + videoRequest.RequireAvc = string.Equals("true", val, StringComparison.OrdinalIgnoreCase); + } + } } } @@ -2115,7 +2122,7 @@ namespace MediaBrowser.Api.Playback if (string.Equals("h264", videoStream.Codec, StringComparison.OrdinalIgnoreCase)) { - if (videoStream.IsAVC.HasValue && !videoStream.IsAVC.Value) + if (videoStream.IsAVC.HasValue && !videoStream.IsAVC.Value && request.RequireAvc) { Logger.Debug("Cannot stream copy video. Stream is marked as not AVC"); return false; diff --git a/MediaBrowser.Api/Playback/StreamRequest.cs b/MediaBrowser.Api/Playback/StreamRequest.cs index 625818d29..50c779765 100644 --- a/MediaBrowser.Api/Playback/StreamRequest.cs +++ b/MediaBrowser.Api/Playback/StreamRequest.cs @@ -195,6 +195,7 @@ namespace MediaBrowser.Api.Playback public bool EnableSubtitlesInManifest { get; set; } public bool EnableSplittingOnNonKeyFrames { get; set; } + public bool RequireAvc { get; set; } public VideoStreamRequest() { diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index c11cfb523..71f0fd541 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -1055,6 +1055,22 @@ namespace MediaBrowser.Model.Dlna } break; } + case ProfileConditionValue.IsAvc: + { + bool isAvc; + if (bool.TryParse(value, out isAvc)) + { + if (isAvc && condition.Condition == ProfileConditionType.Equals) + { + item.RequireAvc = true; + } + else if (!isAvc && condition.Condition == ProfileConditionType.NotEquals) + { + item.RequireAvc = true; + } + } + break; + } case ProfileConditionValue.IsAnamorphic: case ProfileConditionValue.AudioProfile: case ProfileConditionValue.Has64BitOffsets: @@ -1135,6 +1151,8 @@ namespace MediaBrowser.Model.Dlna } break; } + default: + break; } } } diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs index b8db8a10c..e5dd0353e 100644 --- a/MediaBrowser.Model/Dlna/StreamInfo.cs +++ b/MediaBrowser.Model/Dlna/StreamInfo.cs @@ -35,6 +35,7 @@ namespace MediaBrowser.Model.Dlna public string VideoCodec { get; set; } public string VideoProfile { get; set; } + public bool RequireAvc { get; set; } public bool CopyTimestamps { get; set; } public bool EnableSubtitlesInManifest { get; set; } public bool EnableSplittingOnNonKeyFrames { get; set; } @@ -266,6 +267,7 @@ namespace MediaBrowser.Model.Dlna list.Add(new NameValuePair("Tag", item.MediaSource.ETag ?? string.Empty)); list.Add(new NameValuePair("EnableSplittingOnNonKeyFrames", item.EnableSplittingOnNonKeyFrames.ToString().ToLower())); + list.Add(new NameValuePair("RequireAvc", item.RequireAvc.ToString().ToLower())); return list; }