diff options
Diffstat (limited to 'MediaBrowser.ServerApplication')
24 files changed, 669 insertions, 528 deletions
diff --git a/MediaBrowser.ServerApplication/App.xaml.cs b/MediaBrowser.ServerApplication/App.xaml.cs index 69de391a4..706206d3a 100644 --- a/MediaBrowser.ServerApplication/App.xaml.cs +++ b/MediaBrowser.ServerApplication/App.xaml.cs @@ -154,58 +154,5 @@ namespace MediaBrowser.ServerApplication { Dispatcher.Invoke(Shutdown); } - - /// <summary> - /// Opens the dashboard page. - /// </summary> - /// <param name="page">The page.</param> - /// <param name="loggedInUser">The logged in user.</param> - /// <param name="configurationManager">The configuration manager.</param> - /// <param name="appHost">The app host.</param> - public static void OpenDashboardPage(string page, User loggedInUser, IServerConfigurationManager configurationManager, IServerApplicationHost appHost) - { - var url = "http://localhost:" + configurationManager.Configuration.HttpServerPortNumber + "/" + - appHost.WebApplicationName + "/dashboard/" + page; - - OpenUrl(url); - } - - /// <summary> - /// Opens the URL. - /// </summary> - /// <param name="url">The URL.</param> - public static void OpenUrl(string url) - { - var process = new Process - { - StartInfo = new ProcessStartInfo - { - FileName = url - }, - - EnableRaisingEvents = true - }; - - process.Exited += ProcessExited; - - try - { - process.Start(); - } - catch (Exception ex) - { - MessageBox.Show("There was an error launching your web browser. Please check your defualt browser settings."); - } - } - - /// <summary> - /// Processes the exited. - /// </summary> - /// <param name="sender">The sender.</param> - /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> - static void ProcessExited(object sender, EventArgs e) - { - ((Process)sender).Dispose(); - } } } diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 5cae99785..d0f7da73d 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -24,7 +24,6 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Sorting; -using MediaBrowser.IsoMounter; using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; using MediaBrowser.Model.MediaInfo; @@ -36,6 +35,7 @@ using MediaBrowser.Server.Implementations.BdInfo; using MediaBrowser.Server.Implementations.Configuration; using MediaBrowser.Server.Implementations.Drawing; using MediaBrowser.Server.Implementations.Dto; +using MediaBrowser.Server.Implementations.EntryPoints; using MediaBrowser.Server.Implementations.HttpServer; using MediaBrowser.Server.Implementations.IO; using MediaBrowser.Server.Implementations.Library; @@ -46,16 +46,14 @@ using MediaBrowser.Server.Implementations.Providers; using MediaBrowser.Server.Implementations.ServerManager; using MediaBrowser.Server.Implementations.Session; using MediaBrowser.Server.Implementations.WebSocket; -using MediaBrowser.ServerApplication.Implementations; +using MediaBrowser.ServerApplication.FFMpeg; +using MediaBrowser.ServerApplication.Native; using MediaBrowser.WebDashboard.Api; using System; using System.Collections.Generic; -using System.Data.SQLite; -using System.Diagnostics; +using System.Data; using System.IO; using System.Linq; -using System.Net; -using System.Net.Cache; using System.Net.Http; using System.Reflection; using System.Threading; @@ -68,8 +66,6 @@ namespace MediaBrowser.ServerApplication /// </summary> public class ApplicationHost : BaseApplicationHost<ServerApplicationPaths>, IServerApplicationHost { - internal const int UdpServerPort = 7359; - /// <summary> /// Gets the server kernel. /// </summary> @@ -142,11 +138,6 @@ namespace MediaBrowser.ServerApplication /// <value>The provider manager.</value> private IProviderManager ProviderManager { get; set; } /// <summary> - /// Gets or sets the zip client. - /// </summary> - /// <value>The zip client.</value> - private IZipClient ZipClient { get; set; } - /// <summary> /// Gets or sets the HTTP server. /// </summary> /// <value>The HTTP server.</value> @@ -161,6 +152,7 @@ namespace MediaBrowser.ServerApplication private IMediaEncoder MediaEncoder { get; set; } private IIsoManager IsoManager { get; set; } + private ISessionManager SessionManager { get; set; } private ILocalizationManager LocalizationManager { get; set; } @@ -174,14 +166,6 @@ namespace MediaBrowser.ServerApplication private IItemRepository ItemRepository { get; set; } private INotificationsRepository NotificationsRepository { get; set; } - /// <summary> - /// The full path to our startmenu shortcut - /// </summary> - protected override string ProductShortcutPath - { - get { return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu), "Media Browser 3", "Media Browser Server.lnk"); } - } - private Task<IHttpServer> _httpServerCreationTask; /// <summary> @@ -255,8 +239,7 @@ namespace MediaBrowser.ServerApplication RegisterSingleInstance<IBlurayExaminer>(() => new BdInfoExaminer()); - ZipClient = new DotNetZipClient(); - RegisterSingleInstance(ZipClient); + var mediaEncoderTask = RegisterMediaEncoder(); UserDataRepository = new SqliteUserDataRepository(ApplicationPaths, JsonSerializer, LogManager); RegisterSingleInstance(UserDataRepository); @@ -284,10 +267,8 @@ namespace MediaBrowser.ServerApplication RegisterSingleInstance<ILibrarySearchEngine>(() => new LuceneSearchEngine(ApplicationPaths, LogManager, LibraryManager)); - await RegisterMediaEncoder().ConfigureAwait(false); - - var clientConnectionManager = new SessionManager(UserDataRepository, ServerConfigurationManager, Logger, UserRepository); - RegisterSingleInstance<ISessionManager>(clientConnectionManager); + SessionManager = new SessionManager(UserDataRepository, ServerConfigurationManager, Logger, UserRepository); + RegisterSingleInstance<ISessionManager>(SessionManager); HttpServer = await _httpServerCreationTask.ConfigureAwait(false); RegisterSingleInstance(HttpServer, false); @@ -310,7 +291,7 @@ namespace MediaBrowser.ServerApplication await ConfigureNotificationsRepository().ConfigureAwait(false); - await Task.WhenAll(itemsTask, displayPreferencesTask, userdataTask).ConfigureAwait(false); + await Task.WhenAll(itemsTask, displayPreferencesTask, userdataTask, mediaEncoderTask).ConfigureAwait(false); SetKernelProperties(); } @@ -406,27 +387,14 @@ namespace MediaBrowser.ServerApplication /// <param name="dbPath">The db path.</param> /// <returns>Task{IDbConnection}.</returns> /// <exception cref="System.ArgumentNullException">dbPath</exception> - private static async Task<SQLiteConnection> ConnectToDb(string dbPath) + private static Task<IDbConnection> ConnectToDb(string dbPath) { if (string.IsNullOrEmpty(dbPath)) { throw new ArgumentNullException("dbPath"); } - var connectionstr = new SQLiteConnectionStringBuilder - { - PageSize = 4096, - CacheSize = 4096, - SyncMode = SynchronizationModes.Normal, - DataSource = dbPath, - JournalMode = SQLiteJournalModeEnum.Wal - }; - - var connection = new SQLiteConnection(connectionstr.ConnectionString); - - await connection.OpenAsync().ConfigureAwait(false); - - return connection; + return Sqlite.OpenDatabase(dbPath); } /// <summary> @@ -477,6 +445,8 @@ namespace MediaBrowser.ServerApplication IsoManager.AddParts(GetExports<IIsoMounter>()); + SessionManager.AddParts(GetExports<ISessionRemoteController>()); + ImageProcessor.AddParts(GetExports<IImageEnhancer>()); } @@ -527,7 +497,6 @@ namespace MediaBrowser.ServerApplication { NotifyPendingRestart(); } - } /// <summary> @@ -544,7 +513,7 @@ namespace MediaBrowser.ServerApplication Logger.ErrorException("Error sending server restart web socket message", ex); } - MainStartup.Restart(); + NativeApp.Restart(); } /// <summary> @@ -568,44 +537,44 @@ namespace MediaBrowser.ServerApplication /// <returns>IEnumerable{Assembly}.</returns> protected override IEnumerable<Assembly> GetComposablePartAssemblies() { + var list = Directory.EnumerateFiles(ApplicationPaths.PluginsPath, "*.dll", SearchOption.TopDirectoryOnly) + .Select(LoadAssembly) + .Where(a => a != null) + .ToList(); + // Gets all plugin assemblies by first reading all bytes of the .dll and calling Assembly.Load against that // This will prevent the .dll file from getting locked, and allow us to replace it when needed - foreach (var pluginAssembly in Directory - .EnumerateFiles(ApplicationPaths.PluginsPath, "*.dll", SearchOption.TopDirectoryOnly) - .Select(LoadAssembly).Where(a => a != null)) - { - yield return pluginAssembly; - } // Include composable parts in the Api assembly - yield return typeof(ApiEntryPoint).Assembly; + list.Add(typeof(ApiEntryPoint).Assembly); // Include composable parts in the Dashboard assembly - yield return typeof(DashboardInfo).Assembly; + list.Add(typeof(DashboardInfo).Assembly); // Include composable parts in the Model assembly - yield return typeof(SystemInfo).Assembly; + list.Add(typeof(SystemInfo).Assembly); // Include composable parts in the Common assembly - yield return typeof(IApplicationHost).Assembly; + list.Add(typeof(IApplicationHost).Assembly); // Include composable parts in the Controller assembly - yield return typeof(Kernel).Assembly; + list.Add(typeof(Kernel).Assembly); // Include composable parts in the Providers assembly - yield return typeof(ImagesByNameProvider).Assembly; + list.Add(typeof(ImagesByNameProvider).Assembly); // Common implementations - yield return typeof(TaskManager).Assembly; + list.Add(typeof(TaskManager).Assembly); // Server implementations - yield return typeof(ServerApplicationPaths).Assembly; + list.Add(typeof(ServerApplicationPaths).Assembly); - // Pismo - yield return typeof(PismoIsoManager).Assembly; + list.AddRange(Assemblies.GetAssembliesWithParts()); // Include composable parts in the running assembly - yield return GetType().Assembly; + list.Add(GetType().Assembly); + + return list; } private readonly string _systemId = Environment.MachineName.GetMD5().ToString(); @@ -664,7 +633,7 @@ namespace MediaBrowser.ServerApplication Logger.ErrorException("Error sending server shutdown web socket message", ex); } - MainStartup.Shutdown(); + NativeApp.Shutdown(); } /// <summary> @@ -674,36 +643,16 @@ namespace MediaBrowser.ServerApplication { Logger.Info("Requesting administrative access to authorize http server"); - // Create a temp file path to extract the bat file to - var tmpFile = Path.Combine(ConfigurationManager.CommonApplicationPaths.TempDirectory, Guid.NewGuid() + ".bat"); - - // Extract the bat file - using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MediaBrowser.ServerApplication.RegisterServer.bat")) + try { - using (var fileStream = File.Create(tmpFile)) - { - stream.CopyTo(fileStream); - } + ServerAuthorization.AuthorizeServer(ServerConfigurationManager.Configuration.HttpServerPortNumber, + HttpServerUrlPrefix, ServerConfigurationManager.Configuration.LegacyWebSocketPortNumber, + UdpServerEntryPoint.PortNumber, + ConfigurationManager.CommonApplicationPaths.TempDirectory); } - - var startInfo = new ProcessStartInfo - { - FileName = tmpFile, - - Arguments = string.Format("{0} {1} {2} {3}", ServerConfigurationManager.Configuration.HttpServerPortNumber, - HttpServerUrlPrefix, - UdpServerPort, - ServerConfigurationManager.Configuration.LegacyWebSocketPortNumber), - - CreateNoWindow = true, - WindowStyle = ProcessWindowStyle.Hidden, - Verb = "runas", - ErrorDialog = false - }; - - using (var process = Process.Start(startInfo)) + catch (Exception ex) { - process.WaitForExit(); + Logger.ErrorException("Error authorizing server", ex); } } @@ -713,8 +662,7 @@ namespace MediaBrowser.ServerApplication /// <param name="cancellationToken">The cancellation token.</param> /// <param name="progress">The progress.</param> /// <returns>Task{CheckForUpdateResult}.</returns> - public override async Task<CheckForUpdateResult> CheckForApplicationUpdate(CancellationToken cancellationToken, - IProgress<double> progress) + public override async Task<CheckForUpdateResult> CheckForApplicationUpdate(CancellationToken cancellationToken, IProgress<double> progress) { var availablePackages = await InstallationManager.GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false); @@ -745,11 +693,12 @@ namespace MediaBrowser.ServerApplication /// <returns>HttpMessageHandler.</returns> protected override HttpMessageHandler GetHttpMessageHandler(bool enableHttpCompression) { - return new WebRequestHandler - { - CachePolicy = new RequestCachePolicy(RequestCacheLevel.Revalidate), - AutomaticDecompression = enableHttpCompression ? DecompressionMethods.Deflate : DecompressionMethods.None - }; + return HttpMessageHandlerFactory.GetHttpMessageHandler(enableHttpCompression); + } + + protected override void ConfigureAutoRunAtStartup(bool autorun) + { + Autorun.Configure(autorun); } } } diff --git a/MediaBrowser.ServerApplication/EntryPoints/StartupWizard.cs b/MediaBrowser.ServerApplication/EntryPoints/StartupWizard.cs index 87578ef84..1a5f9e2c3 100644 --- a/MediaBrowser.ServerApplication/EntryPoints/StartupWizard.cs +++ b/MediaBrowser.ServerApplication/EntryPoints/StartupWizard.cs @@ -3,9 +3,10 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Plugins; using MediaBrowser.Model.Logging; -using System.ComponentModel; +using System; using System.Linq; -using System.Windows; +using System.Windows.Forms; +using MediaBrowser.ServerApplication.Native; namespace MediaBrowser.ServerApplication.EntryPoints { @@ -31,9 +32,10 @@ namespace MediaBrowser.ServerApplication.EntryPoints /// </summary> /// <param name="appHost">The app host.</param> /// <param name="userManager">The user manager.</param> - public StartupWizard(IServerApplicationHost appHost, IUserManager userManager, IServerConfigurationManager configurationManager) + public StartupWizard(IServerApplicationHost appHost, IUserManager userManager, IServerConfigurationManager configurationManager, ILogger logger) { _appHost = appHost; + _logger = logger; _userManager = userManager; _configurationManager = configurationManager; } @@ -58,9 +60,9 @@ namespace MediaBrowser.ServerApplication.EntryPoints try { - App.OpenDashboardPage("wizardstart.html", user, _configurationManager, _appHost); + BrowserLauncher.OpenDashboardPage("wizardstart.html", user, _configurationManager, _appHost, _logger); } - catch (Win32Exception ex) + catch (Exception ex) { _logger.ErrorException("Error launching startup wizard", ex); @@ -75,4 +77,4 @@ namespace MediaBrowser.ServerApplication.EntryPoints { } } -} +}
\ No newline at end of file diff --git a/MediaBrowser.ServerApplication/EntryPoints/UdpServerEntryPoint.cs b/MediaBrowser.ServerApplication/EntryPoints/UdpServerEntryPoint.cs deleted file mode 100644 index 595d5c89f..000000000 --- a/MediaBrowser.ServerApplication/EntryPoints/UdpServerEntryPoint.cs +++ /dev/null @@ -1,95 +0,0 @@ -using MediaBrowser.Common.Net; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Plugins; -using MediaBrowser.Model.Logging; -using MediaBrowser.Server.Implementations.Udp; -using System.Net.Sockets; - -namespace MediaBrowser.ServerApplication.EntryPoints -{ - /// <summary> - /// Class UdpServerEntryPoint - /// </summary> - public class UdpServerEntryPoint : IServerEntryPoint - { - /// <summary> - /// Gets or sets the UDP server. - /// </summary> - /// <value>The UDP server.</value> - private UdpServer UdpServer { get; set; } - - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - /// <summary> - /// The _network manager - /// </summary> - private readonly INetworkManager _networkManager; - /// <summary> - /// The _server configuration manager - /// </summary> - private readonly IServerConfigurationManager _serverConfigurationManager; - /// <summary> - /// The _HTTP server - /// </summary> - private readonly IHttpServer _httpServer; - - /// <summary> - /// Initializes a new instance of the <see cref="UdpServerEntryPoint"/> class. - /// </summary> - /// <param name="logger">The logger.</param> - /// <param name="networkManager">The network manager.</param> - /// <param name="serverConfigurationManager">The server configuration manager.</param> - /// <param name="httpServer">The HTTP server.</param> - public UdpServerEntryPoint(ILogger logger, INetworkManager networkManager, IServerConfigurationManager serverConfigurationManager, IHttpServer httpServer) - { - _logger = logger; - _networkManager = networkManager; - _serverConfigurationManager = serverConfigurationManager; - _httpServer = httpServer; - } - - /// <summary> - /// Runs this instance. - /// </summary> - public void Run() - { - var udpServer = new UdpServer(_logger, _networkManager, _serverConfigurationManager, _httpServer); - - try - { - udpServer.Start(ApplicationHost.UdpServerPort); - - UdpServer = udpServer; - } - catch (SocketException ex) - { - _logger.ErrorException("Failed to start UDP Server", ex); - } - } - - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() - { - Dispose(true); - } - - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected virtual void Dispose(bool dispose) - { - if (dispose) - { - if (UdpServer != null) - { - UdpServer.Dispose(); - } - } - } - } -} diff --git a/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs b/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs new file mode 100644 index 000000000..926767f5b --- /dev/null +++ b/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs @@ -0,0 +1,302 @@ +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Common.Net; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Net; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.ServerApplication.FFMpeg +{ + public class FFMpegDownloader + { + private readonly IHttpClient _httpClient; + private readonly IApplicationPaths _appPaths; + private readonly ILogger _logger; + private readonly IZipClient _zipClient; + + private const string Version = "ffmpeg20130904"; + + private readonly string[] _fontUrls = new[] + { + "https://www.dropbox.com/s/pj847twf7riq0j7/ARIALUNI.7z?dl=1" + }; + + private readonly string[] _ffMpegUrls = new[] + { + "https://github.com/MediaBrowser/MediaBrowser/raw/master/MediaBrowser.ServerApplication/FFMpeg/ffmpeg-20130904-git-f974289-win32-static.7z", + + "http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20130904-git-f974289-win32-static.7z", + "https://www.dropbox.com/s/a81cb2ob23fwcfs/ffmpeg-20130904-git-f974289-win32-static.7z?dl=1" + }; + + public FFMpegDownloader(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IZipClient zipClient) + { + _logger = logger; + _appPaths = appPaths; + _httpClient = httpClient; + _zipClient = zipClient; + } + + public async Task<FFMpegInfo> GetFFMpegInfo() + { + var versionedDirectoryPath = Path.Combine(GetMediaToolsPath(true), Version); + + var info = new FFMpegInfo + { + ProbePath = Path.Combine(versionedDirectoryPath, "ffprobe.exe"), + Path = Path.Combine(versionedDirectoryPath, "ffmpeg.exe"), + Version = Version + }; + + if (!Directory.Exists(versionedDirectoryPath)) + { + Directory.CreateDirectory(versionedDirectoryPath); + } + + var tasks = new List<Task>(); + + if (!File.Exists(info.ProbePath) || !File.Exists(info.Path)) + { + tasks.Add(DownloadFFMpeg(info)); + } + + tasks.Add(DownloadFonts(versionedDirectoryPath)); + + await Task.WhenAll(tasks).ConfigureAwait(false); + + return info; + } + + private async Task DownloadFFMpeg(FFMpegInfo info) + { + foreach (var url in _ffMpegUrls) + { + try + { + var tempFile = await DownloadFFMpeg(info, url).ConfigureAwait(false); + + ExtractFFMpeg(tempFile, Path.GetDirectoryName(info.Path)); + return; + } + catch (HttpException ex) + { + + } + } + + throw new ApplicationException("Unable to download required components. Please try again later."); + } + + private Task<string> DownloadFFMpeg(FFMpegInfo info, string url) + { + return _httpClient.GetTempFile(new HttpRequestOptions + { + Url = url, + CancellationToken = CancellationToken.None, + Progress = new Progress<double>(), + + // Make it look like a browser + // Try to hide that we're direct linking + UserAgent = "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.47 Safari/537.36" + }); + } + + private void ExtractFFMpeg(string tempFile, string targetFolder) + { + _logger.Debug("Extracting ffmpeg from {0}", tempFile); + + var tempFolder = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString()); + + if (!Directory.Exists(tempFolder)) + { + Directory.CreateDirectory(tempFolder); + } + + try + { + Extract7zArchive(tempFile, tempFolder); + + var files = Directory.EnumerateFiles(tempFolder, "*.exe", SearchOption.AllDirectories).ToList(); + + foreach (var file in files) + { + File.Copy(file, Path.Combine(targetFolder, Path.GetFileName(file))); + } + } + finally + { + DeleteFile(tempFile); + } + } + + private void Extract7zArchive(string archivePath, string targetPath) + { + _zipClient.ExtractAllFrom7z(archivePath, targetPath, true); + } + + private void DeleteFile(string path) + { + try + { + File.Delete(path); + } + catch (IOException ex) + { + _logger.ErrorException("Error deleting temp file {0}", ex, path); + } + } + + /// <summary> + /// Extracts the fonts. + /// </summary> + /// <param name="targetPath">The target path.</param> + private async Task DownloadFonts(string targetPath) + { + try + { + var fontsDirectory = Path.Combine(targetPath, "fonts"); + + if (!Directory.Exists(fontsDirectory)) + { + Directory.CreateDirectory(fontsDirectory); + } + + const string fontFilename = "ARIALUNI.TTF"; + + var fontFile = Path.Combine(fontsDirectory, fontFilename); + + if (!File.Exists(fontFile)) + { + await DownloadFontFile(fontsDirectory, fontFilename).ConfigureAwait(false); + } + + await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false); + } + catch (HttpException ex) + { + // Don't let the server crash because of this + _logger.ErrorException("Error downloading ffmpeg font files", ex); + } + catch (Exception ex) + { + // Don't let the server crash because of this + _logger.ErrorException("Error writing ffmpeg font files", ex); + } + } + + /// <summary> + /// Downloads the font file. + /// </summary> + /// <param name="fontsDirectory">The fonts directory.</param> + /// <param name="fontFilename">The font filename.</param> + /// <returns>Task.</returns> + private async Task DownloadFontFile(string fontsDirectory, string fontFilename) + { + var existingFile = Directory + .EnumerateFiles(_appPaths.ProgramDataPath, fontFilename, SearchOption.AllDirectories) + .FirstOrDefault(); + + if (existingFile != null) + { + try + { + File.Copy(existingFile, Path.Combine(fontsDirectory, fontFilename), true); + return; + } + catch (IOException ex) + { + // Log this, but don't let it fail the operation + _logger.ErrorException("Error copying file", ex); + } + } + + string tempFile = null; + + foreach (var url in _fontUrls) + { + try + { + tempFile = await _httpClient.GetTempFile(new HttpRequestOptions + { + Url = url, + Progress = new Progress<double>() + + }).ConfigureAwait(false); + + break; + } + catch (Exception ex) + { + // The core can function without the font file, so handle this + _logger.ErrorException("Failed to download ffmpeg font file from {0}", ex, url); + } + } + + if (string.IsNullOrEmpty(tempFile)) + { + return; + } + + Extract7zArchive(tempFile, fontsDirectory); + + try + { + File.Delete(tempFile); + } + catch (IOException ex) + { + // Log this, but don't let it fail the operation + _logger.ErrorException("Error deleting temp file {0}", ex, tempFile); + } + } + + /// <summary> + /// Writes the font config file. + /// </summary> + /// <param name="fontsDirectory">The fonts directory.</param> + /// <returns>Task.</returns> + private async Task WriteFontConfigFile(string fontsDirectory) + { + const string fontConfigFilename = "fonts.conf"; + var fontConfigFile = Path.Combine(fontsDirectory, fontConfigFilename); + + if (!File.Exists(fontConfigFile)) + { + var contents = string.Format("<?xml version=\"1.0\"?><fontconfig><dir>{0}</dir><alias><family>Arial</family><prefer>Arial Unicode MS</prefer></alias></fontconfig>", fontsDirectory); + + var bytes = Encoding.UTF8.GetBytes(contents); + + using (var fileStream = new FileStream(fontConfigFile, FileMode.Create, FileAccess.Write, + FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, + FileOptions.Asynchronous)) + { + await fileStream.WriteAsync(bytes, 0, bytes.Length); + } + } + } + + /// <summary> + /// Gets the media tools path. + /// </summary> + /// <param name="create">if set to <c>true</c> [create].</param> + /// <returns>System.String.</returns> + private string GetMediaToolsPath(bool create) + { + var path = Path.Combine(_appPaths.ProgramDataPath, "ffmpeg"); + + if (create && !Directory.Exists(path)) + { + Directory.CreateDirectory(path); + } + + return path; + } + } +} diff --git a/MediaBrowser.ServerApplication/FFMpeg/FFMpegInfo.cs b/MediaBrowser.ServerApplication/FFMpeg/FFMpegInfo.cs new file mode 100644 index 000000000..147a9f771 --- /dev/null +++ b/MediaBrowser.ServerApplication/FFMpeg/FFMpegInfo.cs @@ -0,0 +1,24 @@ +namespace MediaBrowser.ServerApplication.FFMpeg +{ + /// <summary> + /// Class FFMpegInfo + /// </summary> + public class FFMpegInfo + { + /// <summary> + /// Gets or sets the path. + /// </summary> + /// <value>The path.</value> + public string Path { get; set; } + /// <summary> + /// Gets or sets the probe path. + /// </summary> + /// <value>The probe path.</value> + public string ProbePath { get; set; } + /// <summary> + /// Gets or sets the version. + /// </summary> + /// <value>The version.</value> + public string Version { get; set; } + } +}
\ No newline at end of file diff --git a/MediaBrowser.ServerApplication/FFMpeg/ffmpeg-20130904-git-f974289-win32-static.7z.REMOVED.git-id b/MediaBrowser.ServerApplication/FFMpeg/ffmpeg-20130904-git-f974289-win32-static.7z.REMOVED.git-id new file mode 100644 index 000000000..9f83b949b --- /dev/null +++ b/MediaBrowser.ServerApplication/FFMpeg/ffmpeg-20130904-git-f974289-win32-static.7z.REMOVED.git-id @@ -0,0 +1 @@ +8f1dfd62d31e48c31bef4b9ccc0e514f46650a79
\ No newline at end of file diff --git a/MediaBrowser.ServerApplication/Implementations/DotNetZipClient.cs b/MediaBrowser.ServerApplication/Implementations/DotNetZipClient.cs deleted file mode 100644 index 3b174a9b2..000000000 --- a/MediaBrowser.ServerApplication/Implementations/DotNetZipClient.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Ionic.Zip; -using MediaBrowser.Model.IO; -using System.IO; - -namespace MediaBrowser.ServerApplication.Implementations -{ - /// <summary> - /// Class DotNetZipClient - /// </summary> - public class DotNetZipClient : IZipClient - { - /// <summary> - /// Extracts all. - /// </summary> - /// <param name="sourceFile">The source file.</param> - /// <param name="targetPath">The target path.</param> - /// <param name="overwriteExistingFiles">if set to <c>true</c> [overwrite existing files].</param> - public void ExtractAll(string sourceFile, string targetPath, bool overwriteExistingFiles) - { - using (var fileStream = File.OpenRead(sourceFile)) - { - using (var zipFile = ZipFile.Read(fileStream)) - { - zipFile.ExtractAll(targetPath, overwriteExistingFiles ? ExtractExistingFileAction.OverwriteSilently : ExtractExistingFileAction.DoNotOverwrite); - } - } - } - - /// <summary> - /// Extracts all. - /// </summary> - /// <param name="source">The source.</param> - /// <param name="targetPath">The target path.</param> - /// <param name="overwriteExistingFiles">if set to <c>true</c> [overwrite existing files].</param> - public void ExtractAll(Stream source, string targetPath, bool overwriteExistingFiles) - { - using (var zipFile = ZipFile.Read(source)) - { - zipFile.ExtractAll(targetPath, overwriteExistingFiles ? ExtractExistingFileAction.OverwriteSilently : ExtractExistingFileAction.DoNotOverwrite); - } - } - } -} diff --git a/MediaBrowser.ServerApplication/Implementations/FFMpegDownloader.cs b/MediaBrowser.ServerApplication/Implementations/FFMpegDownloader.cs deleted file mode 100644 index 7fd0acddd..000000000 --- a/MediaBrowser.ServerApplication/Implementations/FFMpegDownloader.cs +++ /dev/null @@ -1,205 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.IO; -using MediaBrowser.Common.Net; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Logging; -using System; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; - -namespace MediaBrowser.ServerApplication.Implementations -{ - public class FFMpegDownloader - { - private readonly IZipClient _zipClient; - private readonly IHttpClient _httpClient; - private readonly IApplicationPaths _appPaths; - private readonly ILogger _logger; - - public FFMpegDownloader(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IZipClient zipClient) - { - _logger = logger; - _appPaths = appPaths; - _httpClient = httpClient; - _zipClient = zipClient; - } - - public async Task<FFMpegInfo> GetFFMpegInfo() - { - var assembly = GetType().Assembly; - - var prefix = GetType().Namespace + "."; - - var srch = prefix + "ffmpeg"; - - var resource = assembly.GetManifestResourceNames().First(r => r.StartsWith(srch)); - - var filename = - resource.Substring(resource.IndexOf(prefix, StringComparison.OrdinalIgnoreCase) + prefix.Length); - - var versionedDirectoryPath = Path.Combine(GetMediaToolsPath(true), - Path.GetFileNameWithoutExtension(filename)); - - if (!Directory.Exists(versionedDirectoryPath)) - { - Directory.CreateDirectory(versionedDirectoryPath); - } - - await ExtractTools(assembly, resource, versionedDirectoryPath).ConfigureAwait(false); - - return new FFMpegInfo - { - ProbePath = Path.Combine(versionedDirectoryPath, "ffprobe.exe"), - Path = Path.Combine(versionedDirectoryPath, "ffmpeg.exe"), - Version = Path.GetFileNameWithoutExtension(versionedDirectoryPath) - }; - } - - /// <summary> - /// Extracts the tools. - /// </summary> - /// <param name="assembly">The assembly.</param> - /// <param name="zipFileResourcePath">The zip file resource path.</param> - /// <param name="targetPath">The target path.</param> - private async Task ExtractTools(Assembly assembly, string zipFileResourcePath, string targetPath) - { - using (var resourceStream = assembly.GetManifestResourceStream(zipFileResourcePath)) - { - _zipClient.ExtractAll(resourceStream, targetPath, false); - } - - try - { - await DownloadFonts(targetPath).ConfigureAwait(false); - } - catch (Exception ex) - { - _logger.ErrorException("Error getting ffmpeg font files", ex); - } - } - - private const string FontUrl = "https://www.dropbox.com/s/9nb76tybcsw5xrk/ARIALUNI.zip?dl=1"; - - /// <summary> - /// Extracts the fonts. - /// </summary> - /// <param name="targetPath">The target path.</param> - private async Task DownloadFonts(string targetPath) - { - var fontsDirectory = Path.Combine(targetPath, "fonts"); - - if (!Directory.Exists(fontsDirectory)) - { - Directory.CreateDirectory(fontsDirectory); - } - - const string fontFilename = "ARIALUNI.TTF"; - - var fontFile = Path.Combine(fontsDirectory, fontFilename); - - if (!File.Exists(fontFile)) - { - await DownloadFontFile(fontsDirectory, fontFilename).ConfigureAwait(false); - } - - await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false); - } - - /// <summary> - /// Downloads the font file. - /// </summary> - /// <param name="fontsDirectory">The fonts directory.</param> - /// <param name="fontFilename">The font filename.</param> - /// <returns>Task.</returns> - private async Task DownloadFontFile(string fontsDirectory, string fontFilename) - { - var existingFile = Directory - .EnumerateFiles(_appPaths.ProgramDataPath, fontFilename, SearchOption.AllDirectories) - .FirstOrDefault(); - - if (existingFile != null) - { - try - { - File.Copy(existingFile, Path.Combine(fontsDirectory, fontFilename), true); - return; - } - catch (IOException ex) - { - // Log this, but don't let it fail the operation - _logger.ErrorException("Error copying file", ex); - } - } - - var tempFile = await _httpClient.GetTempFile(new HttpRequestOptions - { - Url = FontUrl, - Progress = new Progress<double>() - }); - - _zipClient.ExtractAll(tempFile, fontsDirectory, true); - - try - { - File.Delete(tempFile); - } - catch (IOException ex) - { - // Log this, but don't let it fail the operation - _logger.ErrorException("Error deleting temp file {0}", ex, tempFile); - } - } - - /// <summary> - /// Writes the font config file. - /// </summary> - /// <param name="fontsDirectory">The fonts directory.</param> - /// <returns>Task.</returns> - private async Task WriteFontConfigFile(string fontsDirectory) - { - const string fontConfigFilename = "fonts.conf"; - var fontConfigFile = Path.Combine(fontsDirectory, fontConfigFilename); - - if (!File.Exists(fontConfigFile)) - { - var contents = string.Format("<?xml version=\"1.0\"?><fontconfig><dir>{0}</dir><alias><family>Arial</family><prefer>Arial Unicode MS</prefer></alias></fontconfig>", fontsDirectory); - - var bytes = Encoding.UTF8.GetBytes(contents); - - using (var fileStream = new FileStream(fontConfigFile, FileMode.Create, FileAccess.Write, - FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, - FileOptions.Asynchronous)) - { - await fileStream.WriteAsync(bytes, 0, bytes.Length); - } - } - } - - /// <summary> - /// Gets the media tools path. - /// </summary> - /// <param name="create">if set to <c>true</c> [create].</param> - /// <returns>System.String.</returns> - private string GetMediaToolsPath(bool create) - { - var path = Path.Combine(_appPaths.ProgramDataPath, "ffmpeg"); - - if (create && !Directory.Exists(path)) - { - Directory.CreateDirectory(path); - } - - return path; - } - } - - public class FFMpegInfo - { - public string Path { get; set; } - public string ProbePath { get; set; } - public string Version { get; set; } - } -} diff --git a/MediaBrowser.ServerApplication/Implementations/ffmpeg20130904.zip.REMOVED.git-id b/MediaBrowser.ServerApplication/Implementations/ffmpeg20130904.zip.REMOVED.git-id deleted file mode 100644 index e99d115a4..000000000 --- a/MediaBrowser.ServerApplication/Implementations/ffmpeg20130904.zip.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -3496b2cde22e7c4cb56b480dd2da637167d51e78
\ No newline at end of file diff --git a/MediaBrowser.ServerApplication/Implementations/readme.txt b/MediaBrowser.ServerApplication/Implementations/readme.txt deleted file mode 100644 index b32dd9aec..000000000 --- a/MediaBrowser.ServerApplication/Implementations/readme.txt +++ /dev/null @@ -1,5 +0,0 @@ -This is the 32-bit static build of ffmpeg, located at: - -http://ffmpeg.zeranoe.com/builds/ - -The zip file contains both ffmpeg and ffprobe, and is suffixed with the date of the build.
\ No newline at end of file diff --git a/MediaBrowser.ServerApplication/MainStartup.cs b/MediaBrowser.ServerApplication/MainStartup.cs index e9c1fdc99..55fa60ed2 100644 --- a/MediaBrowser.ServerApplication/MainStartup.cs +++ b/MediaBrowser.ServerApplication/MainStartup.cs @@ -11,7 +11,6 @@ using System.IO; using System.Linq; using System.ServiceProcess; using System.Threading; -using System.Threading.Tasks; using System.Windows; namespace MediaBrowser.ServerApplication diff --git a/MediaBrowser.ServerApplication/MainWindow.xaml.cs b/MediaBrowser.ServerApplication/MainWindow.xaml.cs index 4c9c065e6..c22c35be8 100644 --- a/MediaBrowser.ServerApplication/MainWindow.xaml.cs +++ b/MediaBrowser.ServerApplication/MainWindow.xaml.cs @@ -12,6 +12,7 @@ using System.Diagnostics; using System.Linq; using System.Windows; using System.Windows.Threading; +using MediaBrowser.ServerApplication.Native; namespace MediaBrowser.ServerApplication { @@ -188,19 +189,19 @@ namespace MediaBrowser.ServerApplication /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> void cmdApiDocs_Click(object sender, EventArgs e) { - App.OpenUrl("http://localhost:" + _configurationManager.Configuration.HttpServerPortNumber + "/" + - _appHost.WebApplicationName + "/metadata"); + BrowserLauncher.OpenUrl("http://localhost:" + _configurationManager.Configuration.HttpServerPortNumber + "/" + + _appHost.WebApplicationName + "/metadata", _logger); } void cmdSwaggerApiDocs_Click(object sender, EventArgs e) { - App.OpenUrl("http://localhost:" + _configurationManager.Configuration.HttpServerPortNumber + "/" + - _appHost.WebApplicationName + "/swagger-ui/index.html"); + BrowserLauncher.OpenUrl("http://localhost:" + _configurationManager.Configuration.HttpServerPortNumber + "/" + + _appHost.WebApplicationName + "/swagger-ui/index.html", _logger); } void cmdGithubWiki_Click(object sender, EventArgs e) { - App.OpenUrl("https://github.com/MediaBrowser/MediaBrowser/wiki"); + BrowserLauncher.OpenUrl("https://github.com/MediaBrowser/MediaBrowser/wiki", _logger); } /// <summary> @@ -254,7 +255,7 @@ namespace MediaBrowser.ServerApplication /// </summary> private void OpenDashboard(User loggedInUser) { - App.OpenDashboardPage("dashboard.html", loggedInUser, _configurationManager, _appHost); + BrowserLauncher.OpenDashboardPage("dashboard.html", loggedInUser, _configurationManager, _appHost, _logger); } /// <summary> @@ -264,7 +265,7 @@ namespace MediaBrowser.ServerApplication /// <param name="e">The <see cref="RoutedEventArgs" /> instance containing the event data.</param> private void cmVisitCT_click(object sender, RoutedEventArgs e) { - App.OpenUrl("http://community.mediabrowser.tv/"); + BrowserLauncher.OpenUrl("http://community.mediabrowser.tv/", _logger); } /// <summary> @@ -275,7 +276,7 @@ namespace MediaBrowser.ServerApplication private void cmdBrowseLibrary_click(object sender, RoutedEventArgs e) { var user = _userManager.Users.FirstOrDefault(u => u.Configuration.IsAdministrator); - App.OpenDashboardPage("index.html", user, _configurationManager, _appHost); + BrowserLauncher.OpenDashboardPage("index.html", user, _configurationManager, _appHost, _logger); } /// <summary> diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 043d5c18f..61ec19dd5 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -130,10 +130,6 @@ <SpecificVersion>False</SpecificVersion> <HintPath>..\packages\MediaBrowser.IsoMounting.3.0.56\lib\net45\MediaBrowser.IsoMounter.dll</HintPath> </Reference> - <Reference Include="MoreLinq, Version=1.0.16006.0, Culture=neutral, PublicKeyToken=384d532d7e88985d, processorArchitecture=MSIL"> - <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\morelinq.1.0.16006\lib\net35\MoreLinq.dll</HintPath> - </Reference> <Reference Include="NLog, Version=2.0.1.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> <HintPath>..\packages\NLog.2.0.1.2\lib\net45\NLog.dll</HintPath> @@ -187,7 +183,6 @@ <Reference Include="System.Net" /> <Reference Include="System.Net.Http" /> <Reference Include="System.Net.Http.WebRequest" /> - <Reference Include="System.Runtime.Remoting" /> <Reference Include="System.ServiceProcess" /> <Reference Include="System.Windows.Forms" /> <Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> @@ -209,12 +204,19 @@ <SubType>Component</SubType> </Compile> <Compile Include="EntryPoints\StartupWizard.cs" /> - <Compile Include="EntryPoints\UdpServerEntryPoint.cs" /> - <Compile Include="Implementations\FFMpegDownloader.cs" /> + <Compile Include="FFMpeg\FFMpegInfo.cs" /> + <Compile Include="Native\Assemblies.cs" /> + <Compile Include="Native\HttpMessageHandlerFactory.cs" /> + <Compile Include="Native\NativeApp.cs" /> + <Compile Include="Native\ServerAuthorization.cs" /> + <Compile Include="Native\Autorun.cs" /> + <Compile Include="Native\BrowserLauncher.cs" /> + <Compile Include="FFMpeg\FFMpegDownloader.cs" /> <Compile Include="MainStartup.cs" /> <Compile Include="BackgroundServiceInstaller.cs"> <SubType>Component</SubType> </Compile> + <Compile Include="Native\Sqlite.cs" /> <Compile Include="Splash\SplashWindow.xaml.cs"> <DependentUpon>SplashWindow.xaml</DependentUpon> </Compile> @@ -242,7 +244,6 @@ <SubType>Code</SubType> </Compile> <Compile Include="ApplicationHost.cs" /> - <Compile Include="Implementations\DotNetZipClient.cs" /> <Compile Include="LibraryExplorer.xaml.cs"> <DependentUpon>LibraryExplorer.xaml</DependentUpon> </Compile> @@ -278,14 +279,15 @@ <LastGenOutput>Resources.Designer.cs</LastGenOutput> </EmbeddedResource> <None Include="app.manifest" /> - <EmbeddedResource Include="Implementations\ffmpeg20130904.zip" /> + <None Include="FFMpeg\ARIALUNI.7z" /> + <None Include="FFMpeg\ffmpeg-20130904-git-f974289-win32-static.7z" /> <None Include="packages.config" /> <None Include="Properties\Settings.settings"> <Generator>SettingsSingleFileGenerator</Generator> <LastGenOutput>Settings.Designer.cs</LastGenOutput> </None> <AppDesigner Include="Properties\" /> - <EmbeddedResource Include="RegisterServer.bat" /> + <EmbeddedResource Include="Native\RegisterServer.bat" /> </ItemGroup> <ItemGroup> <None Include="App.config"> @@ -390,9 +392,6 @@ <ItemGroup> <Resource Include="Resources\Images\mb3logo800.png" /> </ItemGroup> - <ItemGroup> - <EmbeddedResource Include="Implementations\readme.txt" /> - </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <PropertyGroup> <PostBuildEvent>if $(ConfigurationName) == Release ( diff --git a/MediaBrowser.ServerApplication/Native/Assemblies.cs b/MediaBrowser.ServerApplication/Native/Assemblies.cs new file mode 100644 index 000000000..b43dc1a10 --- /dev/null +++ b/MediaBrowser.ServerApplication/Native/Assemblies.cs @@ -0,0 +1,25 @@ +using MediaBrowser.IsoMounter; +using System.Collections.Generic; +using System.Reflection; + +namespace MediaBrowser.ServerApplication.Native +{ + /// <summary> + /// Class Assemblies + /// </summary> + public static class Assemblies + { + /// <summary> + /// Gets the assemblies with parts. + /// </summary> + /// <returns>List{Assembly}.</returns> + public static List<Assembly> GetAssembliesWithParts() + { + var list = new List<Assembly>(); + + list.Add(typeof(PismoIsoManager).Assembly); + + return list; + } + } +} diff --git a/MediaBrowser.ServerApplication/Native/Autorun.cs b/MediaBrowser.ServerApplication/Native/Autorun.cs new file mode 100644 index 000000000..d1c02db84 --- /dev/null +++ b/MediaBrowser.ServerApplication/Native/Autorun.cs @@ -0,0 +1,31 @@ +using System; +using System.IO; + +namespace MediaBrowser.ServerApplication.Native +{ + /// <summary> + /// Class Autorun + /// </summary> + public static class Autorun + { + /// <summary> + /// Configures the specified autorun. + /// </summary> + /// <param name="autorun">if set to <c>true</c> [autorun].</param> + public static void Configure(bool autorun) + { + var shortcutPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu), "Media Browser 3", "Media Browser Server.lnk"); + + if (autorun) + { + //Copy our shortut into the startup folder for this user + File.Copy(shortcutPath, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Startup), Path.GetFileName(shortcutPath) ?? "MBstartup.lnk"), true); + } + else + { + //Remove our shortcut from the startup folder for this user + File.Delete(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Startup), Path.GetFileName(shortcutPath) ?? "MBstartup.lnk")); + } + } + } +} diff --git a/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs b/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs new file mode 100644 index 000000000..e7d041d15 --- /dev/null +++ b/MediaBrowser.ServerApplication/Native/BrowserLauncher.cs @@ -0,0 +1,68 @@ +using MediaBrowser.Controller; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Model.Logging; +using System; +using System.Diagnostics; +using System.Windows.Forms; + +namespace MediaBrowser.ServerApplication.Native +{ + public static class BrowserLauncher + { + /// <summary> + /// Opens the dashboard page. + /// </summary> + /// <param name="page">The page.</param> + /// <param name="loggedInUser">The logged in user.</param> + /// <param name="configurationManager">The configuration manager.</param> + /// <param name="appHost">The app host.</param> + public static void OpenDashboardPage(string page, User loggedInUser, IServerConfigurationManager configurationManager, IServerApplicationHost appHost, ILogger logger) + { + var url = "http://localhost:" + configurationManager.Configuration.HttpServerPortNumber + "/" + + appHost.WebApplicationName + "/dashboard/" + page; + + OpenUrl(url, logger); + } + + /// <summary> + /// Opens the URL. + /// </summary> + /// <param name="url">The URL.</param> + public static void OpenUrl(string url, ILogger logger) + { + var process = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = url + }, + + EnableRaisingEvents = true + }; + + process.Exited += ProcessExited; + + try + { + process.Start(); + } + catch (Exception ex) + { + logger.ErrorException("Error launching url: {0}", ex, url); + + MessageBox.Show("There was an error launching your web browser. Please check your default browser settings."); + } + } + + /// <summary> + /// Processes the exited. + /// </summary> + /// <param name="sender">The sender.</param> + /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> + private static void ProcessExited(object sender, EventArgs e) + { + ((Process)sender).Dispose(); + } + } +} diff --git a/MediaBrowser.ServerApplication/Native/HttpMessageHandlerFactory.cs b/MediaBrowser.ServerApplication/Native/HttpMessageHandlerFactory.cs new file mode 100644 index 000000000..4bbcc9ea0 --- /dev/null +++ b/MediaBrowser.ServerApplication/Native/HttpMessageHandlerFactory.cs @@ -0,0 +1,26 @@ +using System.Net; +using System.Net.Cache; +using System.Net.Http; + +namespace MediaBrowser.ServerApplication.Native +{ + /// <summary> + /// Class HttpMessageHandlerFactory + /// </summary> + public static class HttpMessageHandlerFactory + { + /// <summary> + /// Gets the HTTP message handler. + /// </summary> + /// <param name="enableHttpCompression">if set to <c>true</c> [enable HTTP compression].</param> + /// <returns>HttpMessageHandler.</returns> + public static HttpMessageHandler GetHttpMessageHandler(bool enableHttpCompression) + { + return new WebRequestHandler + { + CachePolicy = new RequestCachePolicy(RequestCacheLevel.Revalidate), + AutomaticDecompression = enableHttpCompression ? DecompressionMethods.Deflate : DecompressionMethods.None + }; + } + } +} diff --git a/MediaBrowser.ServerApplication/Native/NativeApp.cs b/MediaBrowser.ServerApplication/Native/NativeApp.cs new file mode 100644 index 000000000..ea4218afc --- /dev/null +++ b/MediaBrowser.ServerApplication/Native/NativeApp.cs @@ -0,0 +1,25 @@ + +namespace MediaBrowser.ServerApplication.Native +{ + /// <summary> + /// Class NativeApp + /// </summary> + public static class NativeApp + { + /// <summary> + /// Shutdowns this instance. + /// </summary> + public static void Shutdown() + { + MainStartup.Shutdown(); + } + + /// <summary> + /// Restarts this instance. + /// </summary> + public static void Restart() + { + MainStartup.Restart(); + } + } +} diff --git a/MediaBrowser.ServerApplication/RegisterServer.bat b/MediaBrowser.ServerApplication/Native/RegisterServer.bat index d762dfaf7..d762dfaf7 100644 --- a/MediaBrowser.ServerApplication/RegisterServer.bat +++ b/MediaBrowser.ServerApplication/Native/RegisterServer.bat diff --git a/MediaBrowser.ServerApplication/Native/ServerAuthorization.cs b/MediaBrowser.ServerApplication/Native/ServerAuthorization.cs new file mode 100644 index 000000000..91f0974eb --- /dev/null +++ b/MediaBrowser.ServerApplication/Native/ServerAuthorization.cs @@ -0,0 +1,56 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Reflection; + +namespace MediaBrowser.ServerApplication.Native +{ + /// <summary> + /// Class Authorization + /// </summary> + public static class ServerAuthorization + { + /// <summary> + /// Authorizes the server. + /// </summary> + /// <param name="httpServerPort">The HTTP server port.</param> + /// <param name="httpServerUrlPrefix">The HTTP server URL prefix.</param> + /// <param name="webSocketPort">The web socket port.</param> + /// <param name="udpPort">The UDP port.</param> + /// <param name="tempDirectory">The temp directory.</param> + public static void AuthorizeServer(int httpServerPort, string httpServerUrlPrefix, int webSocketPort, int udpPort, string tempDirectory) + { + // Create a temp file path to extract the bat file to + var tmpFile = Path.Combine(tempDirectory, Guid.NewGuid() + ".bat"); + + // Extract the bat file + using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(typeof(ServerAuthorization).Namespace + ".RegisterServer.bat")) + { + using (var fileStream = File.Create(tmpFile)) + { + stream.CopyTo(fileStream); + } + } + + var startInfo = new ProcessStartInfo + { + FileName = tmpFile, + + Arguments = string.Format("{0} {1} {2} {3}", httpServerPort, + httpServerUrlPrefix, + udpPort, + webSocketPort), + + CreateNoWindow = true, + WindowStyle = ProcessWindowStyle.Hidden, + Verb = "runas", + ErrorDialog = false + }; + + using (var process = Process.Start(startInfo)) + { + process.WaitForExit(); + } + } + } +} diff --git a/MediaBrowser.ServerApplication/Native/Sqlite.cs b/MediaBrowser.ServerApplication/Native/Sqlite.cs new file mode 100644 index 000000000..cc20952d7 --- /dev/null +++ b/MediaBrowser.ServerApplication/Native/Sqlite.cs @@ -0,0 +1,36 @@ +using System.Data; +using System.Data.SQLite; +using System.Threading.Tasks; + +namespace MediaBrowser.ServerApplication.Native +{ + /// <summary> + /// Class Sqlite + /// </summary> + public static class Sqlite + { + /// <summary> + /// Connects to db. + /// </summary> + /// <param name="dbPath">The db path.</param> + /// <returns>Task{IDbConnection}.</returns> + /// <exception cref="System.ArgumentNullException">dbPath</exception> + public static async Task<IDbConnection> OpenDatabase(string dbPath) + { + var connectionstr = new SQLiteConnectionStringBuilder + { + PageSize = 4096, + CacheSize = 4096, + SyncMode = SynchronizationModes.Normal, + DataSource = dbPath, + JournalMode = SQLiteJournalModeEnum.Wal + }; + + var connection = new SQLiteConnection(connectionstr.ConnectionString); + + await connection.OpenAsync().ConfigureAwait(false); + + return connection; + } + } +} diff --git a/MediaBrowser.ServerApplication/Resources/Images/mb3logo800.png b/MediaBrowser.ServerApplication/Resources/Images/mb3logo800.png Binary files differindex fbc769a6f..12db84679 100644 --- a/MediaBrowser.ServerApplication/Resources/Images/mb3logo800.png +++ b/MediaBrowser.ServerApplication/Resources/Images/mb3logo800.png diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config index 8c1821ca5..e680b556f 100644 --- a/MediaBrowser.ServerApplication/packages.config +++ b/MediaBrowser.ServerApplication/packages.config @@ -4,7 +4,6 @@ <package id="Hardcodet.Wpf.TaskbarNotification" version="1.0.4.0" targetFramework="net45" /> <package id="MahApps.Metro" version="0.11.0.17-ALPHA" targetFramework="net45" /> <package id="MediaBrowser.IsoMounting" version="3.0.56" targetFramework="net45" /> - <package id="morelinq" version="1.0.16006" targetFramework="net45" /> <package id="NLog" version="2.0.1.2" targetFramework="net45" /> <package id="ServiceStack" version="3.9.62" targetFramework="net45" /> <package id="ServiceStack.Common" version="3.9.62" targetFramework="net45" /> |
