From a02333fb0cbda8227dd6a5662c6a880eafd5074c Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 23 Sep 2013 12:00:22 -0400 Subject: #429 - Extract ffmpeg from core product --- MediaBrowser.ServerApplication/ApplicationHost.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'MediaBrowser.ServerApplication/ApplicationHost.cs') diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 5cae99785..a2965d4ea 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -258,6 +258,8 @@ namespace MediaBrowser.ServerApplication ZipClient = new DotNetZipClient(); RegisterSingleInstance(ZipClient); + var mediaEncoderTask = RegisterMediaEncoder(); + UserDataRepository = new SqliteUserDataRepository(ApplicationPaths, JsonSerializer, LogManager); RegisterSingleInstance(UserDataRepository); @@ -284,8 +286,6 @@ namespace MediaBrowser.ServerApplication RegisterSingleInstance(() => new LuceneSearchEngine(ApplicationPaths, LogManager, LibraryManager)); - await RegisterMediaEncoder().ConfigureAwait(false); - var clientConnectionManager = new SessionManager(UserDataRepository, ServerConfigurationManager, Logger, UserRepository); RegisterSingleInstance(clientConnectionManager); @@ -310,7 +310,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(); } -- cgit v1.2.3 From db0264e80fa84aba2263f22b799e5a9f4359b490 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 23 Sep 2013 13:14:17 -0400 Subject: fixes #429 - Extract ffmpeg from core product --- MediaBrowser.ServerApplication/ApplicationHost.cs | 2 +- .../Implementations/FFMpegDownloader.cs | 117 +++++++++++++++++---- 2 files changed, 97 insertions(+), 22 deletions(-) (limited to 'MediaBrowser.ServerApplication/ApplicationHost.cs') diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index a2965d4ea..eeea9392c 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -321,7 +321,7 @@ namespace MediaBrowser.ServerApplication /// Task. private async Task RegisterMediaEncoder() { - var info = await new FFMpegDownloader(Logger, ApplicationPaths, HttpClient, ZipClient).GetFFMpegInfo().ConfigureAwait(false); + var info = await new FFMpegDownloader(Logger, ApplicationPaths, HttpClient).GetFFMpegInfo().ConfigureAwait(false); MediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), ApplicationPaths, JsonSerializer, info.Path, info.ProbePath, info.Version); RegisterSingleInstance(MediaEncoder); diff --git a/MediaBrowser.ServerApplication/Implementations/FFMpegDownloader.cs b/MediaBrowser.ServerApplication/Implementations/FFMpegDownloader.cs index becb8d8ab..ef33518cd 100644 --- a/MediaBrowser.ServerApplication/Implementations/FFMpegDownloader.cs +++ b/MediaBrowser.ServerApplication/Implementations/FFMpegDownloader.cs @@ -1,42 +1,52 @@ 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 SharpCompress.Archive.SevenZip; +using SharpCompress.Common; +using SharpCompress.Reader; using System; using System.IO; using System.Linq; using System.Text; +using System.Threading; 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) + private const string Version = "ffmpeg20130904"; + + private const string FontUrl = "https://www.dropbox.com/s/pj847twf7riq0j7/ARIALUNI.7z?dl=1"; + + private readonly string[] _ffMpegUrls = new[] + { + "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) { _logger = logger; _appPaths = appPaths; _httpClient = httpClient; - _zipClient = zipClient; } public async Task GetFFMpegInfo() { - var version = "ffmpeg20130904"; - - var versionedDirectoryPath = Path.Combine(GetMediaToolsPath(true), version); + 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 + Version = Version }; if (!Directory.Exists(versionedDirectoryPath)) @@ -46,7 +56,7 @@ namespace MediaBrowser.ServerApplication.Implementations if (!File.Exists(info.ProbePath) || !File.Exists(info.Path)) { - ExtractTools(version, versionedDirectoryPath); + await DownloadFFMpeg(info).ConfigureAwait(false); } try @@ -61,23 +71,88 @@ namespace MediaBrowser.ServerApplication.Implementations return info; } - /// - /// Extracts the tools. - /// - /// The assembly. - /// The zip file resource path. - /// The target path. - private void ExtractTools(string version, string targetPath) + private async Task DownloadFFMpeg(FFMpegInfo info) { - var zipFileResourcePath = GetType().Namespace + "." + version + ".zip"; + foreach (var url in _ffMpegUrls) + { + try + { + var tempFile = await DownloadFFMpeg(info, url).ConfigureAwait(false); - using (var resourceStream = GetType().Assembly.GetManifestResourceStream(zipFileResourcePath)) + ExtractFFMpeg(tempFile, Path.GetDirectoryName(info.Path)); + return; + } + catch (HttpException ex) + { + + } + } + } + + private Task DownloadFFMpeg(FFMpegInfo info, string url) + { + return _httpClient.GetTempFile(new HttpRequestOptions { - _zipClient.ExtractAll(resourceStream, targetPath, false); + Url = url, + CancellationToken = CancellationToken.None, + Progress = new Progress(), + + // 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) + { + using (var archive = SevenZipArchive.Open(archivePath)) + { + using (var reader = archive.ExtractAllEntries()) + { + reader.WriteAllToDirectory(targetPath, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite); + } } } - private const string FontUrl = "https://www.dropbox.com/s/9nb76tybcsw5xrk/ARIALUNI.zip?dl=1"; + private void DeleteFile(string path) + { + try + { + File.Delete(path); + } + catch (IOException ex) + { + _logger.ErrorException("Error deleting temp file {0}", ex, path); + } + } /// /// Extracts the fonts. @@ -136,7 +211,7 @@ namespace MediaBrowser.ServerApplication.Implementations Progress = new Progress() }); - _zipClient.ExtractAll(tempFile, fontsDirectory, true); + Extract7zArchive(tempFile, fontsDirectory); try { -- cgit v1.2.3 From 51b01d0f6d21bf31a093cf7d8f88e31aba884288 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 23 Sep 2013 14:53:06 -0400 Subject: updated nuget --- .../ScheduledTasks/TaskManager.cs | 15 ++++++- MediaBrowser.Common/ScheduledTasks/ITaskManager.cs | 7 ++++ MediaBrowser.ServerApplication/ApplicationHost.cs | 2 +- .../Implementations/DotNetZipClient.cs | 48 ---------------------- .../Implementations/ZipClient.cs | 48 ++++++++++++++++++++++ .../MediaBrowser.ServerApplication.csproj | 2 +- Nuget/MediaBrowser.Common.Internal.nuspec | 4 +- Nuget/MediaBrowser.Common.nuspec | 2 +- Nuget/MediaBrowser.Server.Core.nuspec | 4 +- 9 files changed, 75 insertions(+), 57 deletions(-) delete mode 100644 MediaBrowser.ServerApplication/Implementations/DotNetZipClient.cs create mode 100644 MediaBrowser.ServerApplication/Implementations/ZipClient.cs (limited to 'MediaBrowser.ServerApplication/ApplicationHost.cs') diff --git a/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs b/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs index 8278c8a28..6605432fa 100644 --- a/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs +++ b/MediaBrowser.Common.Implementations/ScheduledTasks/TaskManager.cs @@ -1,5 +1,4 @@ -using System.Threading.Tasks; -using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Events; using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Model.Logging; @@ -8,6 +7,7 @@ using MediaBrowser.Model.Tasks; using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; namespace MediaBrowser.Common.Implementations.ScheduledTasks { @@ -77,6 +77,17 @@ namespace MediaBrowser.Common.Implementations.ScheduledTasks QueueScheduledTask(); } + /// + /// Cancels if running + /// + /// + public void CancelIfRunning() + where T : IScheduledTask + { + var task = ScheduledTasks.First(t => t.ScheduledTask.GetType() == typeof(T)); + ((ScheduledTaskWorker)task).CancelIfRunning(); + } + /// /// Queues the scheduled task. /// diff --git a/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs b/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs index ec0e7c1c9..394872783 100644 --- a/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs +++ b/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs @@ -21,6 +21,13 @@ namespace MediaBrowser.Common.ScheduledTasks void CancelIfRunningAndQueue() where T : IScheduledTask; + /// + /// Cancels if running. + /// + /// + void CancelIfRunning() + where T : IScheduledTask; + /// /// Queues the scheduled task. /// diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index eeea9392c..7a99693a6 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -255,7 +255,7 @@ namespace MediaBrowser.ServerApplication RegisterSingleInstance(() => new BdInfoExaminer()); - ZipClient = new DotNetZipClient(); + ZipClient = new ZipClient(); RegisterSingleInstance(ZipClient); var mediaEncoderTask = RegisterMediaEncoder(); diff --git a/MediaBrowser.ServerApplication/Implementations/DotNetZipClient.cs b/MediaBrowser.ServerApplication/Implementations/DotNetZipClient.cs deleted file mode 100644 index 4a9afac3f..000000000 --- a/MediaBrowser.ServerApplication/Implementations/DotNetZipClient.cs +++ /dev/null @@ -1,48 +0,0 @@ -using MediaBrowser.Model.IO; -using SharpCompress.Common; -using SharpCompress.Reader; -using System.IO; - -namespace MediaBrowser.ServerApplication.Implementations -{ - /// - /// Class DotNetZipClient - /// - public class DotNetZipClient : IZipClient - { - /// - /// Extracts all. - /// - /// The source file. - /// The target path. - /// if set to true [overwrite existing files]. - public void ExtractAll(string sourceFile, string targetPath, bool overwriteExistingFiles) - { - using (var fileStream = File.OpenRead(sourceFile)) - { - ExtractAll(fileStream, targetPath, overwriteExistingFiles); - } - } - - /// - /// Extracts all. - /// - /// The source. - /// The target path. - /// if set to true [overwrite existing files]. - public void ExtractAll(Stream source, string targetPath, bool overwriteExistingFiles) - { - using (var reader = ReaderFactory.Open(source)) - { - var options = ExtractOptions.ExtractFullPath; - - if (overwriteExistingFiles) - { - options = options | ExtractOptions.Overwrite; - } - - reader.WriteAllToDirectory(targetPath, options); - } - } - } -} diff --git a/MediaBrowser.ServerApplication/Implementations/ZipClient.cs b/MediaBrowser.ServerApplication/Implementations/ZipClient.cs new file mode 100644 index 000000000..e9e8645e9 --- /dev/null +++ b/MediaBrowser.ServerApplication/Implementations/ZipClient.cs @@ -0,0 +1,48 @@ +using MediaBrowser.Model.IO; +using SharpCompress.Common; +using SharpCompress.Reader; +using System.IO; + +namespace MediaBrowser.ServerApplication.Implementations +{ + /// + /// Class DotNetZipClient + /// + public class ZipClient : IZipClient + { + /// + /// Extracts all. + /// + /// The source file. + /// The target path. + /// if set to true [overwrite existing files]. + public void ExtractAll(string sourceFile, string targetPath, bool overwriteExistingFiles) + { + using (var fileStream = File.OpenRead(sourceFile)) + { + ExtractAll(fileStream, targetPath, overwriteExistingFiles); + } + } + + /// + /// Extracts all. + /// + /// The source. + /// The target path. + /// if set to true [overwrite existing files]. + public void ExtractAll(Stream source, string targetPath, bool overwriteExistingFiles) + { + using (var reader = ReaderFactory.Open(source)) + { + var options = ExtractOptions.ExtractFullPath; + + if (overwriteExistingFiles) + { + options = options | ExtractOptions.Overwrite; + } + + reader.WriteAllToDirectory(targetPath, options); + } + } + } +} diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index cc799f6ba..793489c1f 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -245,7 +245,7 @@ Code - + LibraryExplorer.xaml diff --git a/Nuget/MediaBrowser.Common.Internal.nuspec b/Nuget/MediaBrowser.Common.Internal.nuspec index d3fd7a35e..eb846cd2f 100644 --- a/Nuget/MediaBrowser.Common.Internal.nuspec +++ b/Nuget/MediaBrowser.Common.Internal.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common.Internal - 3.0.207 + 3.0.208 MediaBrowser.Common.Internal Luke ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption. Copyright © Media Browser 2013 - + diff --git a/Nuget/MediaBrowser.Common.nuspec b/Nuget/MediaBrowser.Common.nuspec index 5cddfbc76..ba211c3d6 100644 --- a/Nuget/MediaBrowser.Common.nuspec +++ b/Nuget/MediaBrowser.Common.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Common - 3.0.207 + 3.0.208 MediaBrowser.Common Media Browser Team ebr,Luke,scottisafool diff --git a/Nuget/MediaBrowser.Server.Core.nuspec b/Nuget/MediaBrowser.Server.Core.nuspec index 0c738ce93..c6f801a9b 100644 --- a/Nuget/MediaBrowser.Server.Core.nuspec +++ b/Nuget/MediaBrowser.Server.Core.nuspec @@ -2,7 +2,7 @@ MediaBrowser.Server.Core - 3.0.207 + 3.0.208 Media Browser.Server.Core Media Browser Team ebr,Luke,scottisafool @@ -12,7 +12,7 @@ Contains core components required to build plugins for Media Browser Server. Copyright © Media Browser 2013 - + -- cgit v1.2.3 From c61cc4a304978a59f66c86c3618f8f6dd8ccca7b Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 24 Sep 2013 11:42:30 -0400 Subject: support more kinds of remote control besides web socket --- MediaBrowser.Api/SessionsService.cs | 40 +------------ .../MediaBrowser.Controller.csproj | 1 + MediaBrowser.Controller/Session/ISessionManager.cs | 17 ++++++ .../Session/ISessionRemoteController.cs | 25 +++++++++ .../MediaBrowser.Server.Implementations.csproj | 1 + .../Session/SessionManager.cs | 65 ++++++++++++++++++++-- .../Session/WebSocketController.cs | 52 +++++++++++++++++ MediaBrowser.ServerApplication/ApplicationHost.cs | 7 ++- 8 files changed, 163 insertions(+), 45 deletions(-) create mode 100644 MediaBrowser.Controller/Session/ISessionRemoteController.cs create mode 100644 MediaBrowser.Server.Implementations/Session/WebSocketController.cs (limited to 'MediaBrowser.ServerApplication/ApplicationHost.cs') diff --git a/MediaBrowser.Api/SessionsService.cs b/MediaBrowser.Api/SessionsService.cs index cad3c4384..b93b5326e 100644 --- a/MediaBrowser.Api/SessionsService.cs +++ b/MediaBrowser.Api/SessionsService.cs @@ -325,49 +325,11 @@ namespace MediaBrowser.Api /// The request. public void Post(SendSystemCommand request) { - var task = SendSystemCommand(request); + var task = _sessionManager.SendSystemCommand(request.Id, request.Command, CancellationToken.None); Task.WaitAll(task); } - private async Task SendSystemCommand(SendSystemCommand request) - { - var session = _sessionManager.Sessions.FirstOrDefault(i => i.Id == request.Id); - - if (session == null) - { - throw new ResourceNotFoundException(string.Format("Session {0} not found.", request.Id)); - } - - if (!session.SupportsRemoteControl) - { - throw new ArgumentException(string.Format("Session {0} does not support remote control.", session.Id)); - } - - var socket = session.WebSockets.OrderByDescending(i => i.LastActivityDate).FirstOrDefault(i => i.State == WebSocketState.Open); - - if (socket != null) - { - try - { - await socket.SendAsync(new WebSocketMessage - { - MessageType = "SystemCommand", - Data = request.Command.ToString() - - }, CancellationToken.None).ConfigureAwait(false); - } - catch (Exception ex) - { - Logger.ErrorException("Error sending web socket message", ex); - } - } - else - { - throw new InvalidOperationException("The requested session does not have an open web socket."); - } - } - /// /// Posts the specified request. /// diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 80cf82da1..b5ad862be 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -165,6 +165,7 @@ + diff --git a/MediaBrowser.Controller/Session/ISessionManager.cs b/MediaBrowser.Controller/Session/ISessionManager.cs index fba1d26e8..f8f7ded2b 100644 --- a/MediaBrowser.Controller/Session/ISessionManager.cs +++ b/MediaBrowser.Controller/Session/ISessionManager.cs @@ -1,7 +1,9 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Session; using System; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.Controller.Session @@ -11,6 +13,12 @@ namespace MediaBrowser.Controller.Session /// public interface ISessionManager { + /// + /// Adds the parts. + /// + /// The remote controllers. + void AddParts(IEnumerable remoteControllers); + /// /// Occurs when [playback start]. /// @@ -72,5 +80,14 @@ namespace MediaBrowser.Controller.Session /// Task. /// Task OnPlaybackStopped(BaseItem item, long? positionTicks, Guid sessionId); + + /// + /// Sends the system command. + /// + /// The session id. + /// The command. + /// The cancellation token. + /// Task. + Task SendSystemCommand(Guid sessionId, SystemCommand command, CancellationToken cancellationToken); } } \ No newline at end of file diff --git a/MediaBrowser.Controller/Session/ISessionRemoteController.cs b/MediaBrowser.Controller/Session/ISessionRemoteController.cs new file mode 100644 index 000000000..1f6faeb9c --- /dev/null +++ b/MediaBrowser.Controller/Session/ISessionRemoteController.cs @@ -0,0 +1,25 @@ +using MediaBrowser.Model.Session; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Controller.Session +{ + public interface ISessionRemoteController + { + /// + /// Supportses the specified session. + /// + /// The session. + /// true if XXXX, false otherwise + bool Supports(SessionInfo session); + + /// + /// Sends the system command. + /// + /// The session. + /// The command. + /// The cancellation token. + /// Task. + Task SendSystemCommand(SessionInfo session, SystemCommand command, CancellationToken cancellationToken); + } +} diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 9d2fc8c6b..3c2021750 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -183,6 +183,7 @@ Code + diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index 65ec02d12..5b0d957ae 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -1,4 +1,5 @@ using MediaBrowser.Common.Events; +using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; @@ -6,6 +7,7 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Persistence; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Session; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -75,6 +77,12 @@ namespace MediaBrowser.Server.Implementations.Session _userRepository = userRepository; } + private List _remoteControllers; + public void AddParts(IEnumerable remoteControllers) + { + _remoteControllers = remoteControllers.ToList(); + } + /// /// Gets all connections. /// @@ -122,7 +130,7 @@ namespace MediaBrowser.Server.Implementations.Session var activityDate = DateTime.UtcNow; var session = GetSessionInfo(clientType, appVersion, deviceId, deviceName, user); - + session.LastActivityDate = activityDate; if (user == null) @@ -233,7 +241,7 @@ namespace MediaBrowser.Server.Implementations.Session var key = item.GetUserDataKey(); var user = session.User; - + var data = _userDataRepository.GetUserData(user.Id, key); data.PlayCount++; @@ -321,7 +329,7 @@ namespace MediaBrowser.Server.Implementations.Session { throw new ArgumentOutOfRangeException("positionTicks"); } - + var session = Sessions.First(i => i.Id.Equals(sessionId)); RemoveNowPlayingItem(session, item); @@ -329,7 +337,7 @@ namespace MediaBrowser.Server.Implementations.Session var key = item.GetUserDataKey(); var user = session.User; - + var data = _userDataRepository.GetUserData(user.Id, key); if (positionTicks.HasValue) @@ -408,5 +416,54 @@ namespace MediaBrowser.Server.Implementations.Session data.PlaybackPositionTicks = positionTicks; } + + /// + /// Gets the session for remote control. + /// + /// The session id. + /// SessionInfo. + /// + private SessionInfo GetSessionForRemoteControl(Guid sessionId) + { + var session = Sessions.First(i => i.Id.Equals(sessionId)); + + if (session == null) + { + throw new ResourceNotFoundException(string.Format("Session {0} not found.", sessionId)); + } + + if (!session.SupportsRemoteControl) + { + throw new ArgumentException(string.Format("Session {0} does not support remote control.", session.Id)); + } + + return session; + } + + /// + /// Gets the controllers. + /// + /// The session. + /// IEnumerable{ISessionRemoteController}. + private IEnumerable GetControllers(SessionInfo session) + { + return _remoteControllers.Where(i => i.Supports(session)); + } + + /// + /// Sends the system command. + /// + /// The session id. + /// The command. + /// The cancellation token. + /// Task. + public Task SendSystemCommand(Guid sessionId, SystemCommand command, CancellationToken cancellationToken) + { + var session = GetSessionForRemoteControl(sessionId); + + var tasks = GetControllers(session).Select(i => i.SendSystemCommand(session, command, cancellationToken)); + + return Task.WhenAll(tasks); + } } } diff --git a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs new file mode 100644 index 000000000..daa4c7d81 --- /dev/null +++ b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs @@ -0,0 +1,52 @@ +using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.Net; +using MediaBrowser.Model.Session; +using System; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +namespace MediaBrowser.Server.Implementations.Session +{ + public class WebSocketController : ISessionRemoteController + { + private readonly ILogger _logger; + + public WebSocketController(ILogger logger) + { + _logger = logger; + } + + public bool Supports(SessionInfo session) + { + return session.WebSockets.Any(i => i.State == WebSocketState.Open); + } + + public async Task SendSystemCommand(SessionInfo session, SystemCommand command, CancellationToken cancellationToken) + { + var socket = session.WebSockets.OrderByDescending(i => i.LastActivityDate).FirstOrDefault(i => i.State == WebSocketState.Open); + + if (socket != null) + { + try + { + await socket.SendAsync(new WebSocketMessage + { + MessageType = "SystemCommand", + Data = command.ToString() + + }, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error sending web socket message", ex); + } + } + else + { + throw new InvalidOperationException("The requested session does not have an open web socket."); + } + } + } +} diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 7a99693a6..e96516603 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -161,6 +161,7 @@ namespace MediaBrowser.ServerApplication private IMediaEncoder MediaEncoder { get; set; } private IIsoManager IsoManager { get; set; } + private ISessionManager SessionManager { get; set; } private ILocalizationManager LocalizationManager { get; set; } @@ -286,8 +287,8 @@ namespace MediaBrowser.ServerApplication RegisterSingleInstance(() => new LuceneSearchEngine(ApplicationPaths, LogManager, LibraryManager)); - var clientConnectionManager = new SessionManager(UserDataRepository, ServerConfigurationManager, Logger, UserRepository); - RegisterSingleInstance(clientConnectionManager); + SessionManager = new SessionManager(UserDataRepository, ServerConfigurationManager, Logger, UserRepository); + RegisterSingleInstance(SessionManager); HttpServer = await _httpServerCreationTask.ConfigureAwait(false); RegisterSingleInstance(HttpServer, false); @@ -477,6 +478,8 @@ namespace MediaBrowser.ServerApplication IsoManager.AddParts(GetExports()); + SessionManager.AddParts(GetExports()); + ImageProcessor.AddParts(GetExports()); } -- cgit v1.2.3 From fe5a9232c84cea113336005b3c7cbd7fe77a2d80 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Tue, 24 Sep 2013 20:54:51 -0400 Subject: moved a few things for mono --- .../Archiving/ZipClient.cs | 87 ++++++ .../BaseApplicationHost.cs | 59 ++-- .../MediaBrowser.Common.Implementations.csproj | 4 + .../packages.config | 1 + MediaBrowser.Model/IO/IZipClient.cs | 16 ++ MediaBrowser.Mono.userprefs | 13 +- .../EntryPoints/UdpServerEntryPoint.cs | 97 +++++++ .../MediaBrowser.Server.Implementations.csproj | 1 + .../FFMpeg/FFMpegDownloader.cs | 36 +++ .../MediaBrowser.Server.Mono.csproj | 28 ++ MediaBrowser.Server.Mono/Native/Assemblies.cs | 22 ++ MediaBrowser.Server.Mono/Native/Autorun.cs | 20 ++ .../Native/HttpMessageHandlerFactory.cs | 25 ++ MediaBrowser.Server.Mono/Native/NativeApp.cs | 25 ++ .../Native/ServerAuthorization.cs | 26 ++ MediaBrowser.Server.Mono/Native/Sqlite.cs | 36 +++ MediaBrowser.Server.Mono/gtk-gui/gui.stetic | 1 + MediaBrowser.ServerApplication/App.xaml.cs | 53 ---- MediaBrowser.ServerApplication/ApplicationHost.cs | 136 +++------ .../EntryPoints/StartupWizard.cs | 14 +- .../EntryPoints/UdpServerEntryPoint.cs | 95 ------- .../FFMpeg/FFMpegDownloader.cs | 302 ++++++++++++++++++++ .../FFMpeg/FFMpegInfo.cs | 24 ++ ...0904-git-f974289-win32-static.7z.REMOVED.git-id | 1 + .../Implementations/FFMpegDownloader.cs | 315 --------------------- .../Implementations/ZipClient.cs | 48 ---- ...0904-git-f974289-win32-static.7z.REMOVED.git-id | 1 - MediaBrowser.ServerApplication/MainStartup.cs | 1 - MediaBrowser.ServerApplication/MainWindow.xaml.cs | 17 +- .../MediaBrowser.ServerApplication.csproj | 26 +- .../Native/Assemblies.cs | 25 ++ MediaBrowser.ServerApplication/Native/Autorun.cs | 31 ++ .../Native/BrowserLauncher.cs | 68 +++++ .../Native/HttpMessageHandlerFactory.cs | 26 ++ MediaBrowser.ServerApplication/Native/NativeApp.cs | 25 ++ .../Native/RegisterServer.bat | 28 ++ .../Native/ServerAuthorization.cs | 56 ++++ MediaBrowser.ServerApplication/Native/Sqlite.cs | 36 +++ MediaBrowser.ServerApplication/RegisterServer.bat | 28 -- MediaBrowser.ServerApplication/packages.config | 2 - 40 files changed, 1158 insertions(+), 697 deletions(-) create mode 100644 MediaBrowser.Common.Implementations/Archiving/ZipClient.cs create mode 100644 MediaBrowser.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs create mode 100644 MediaBrowser.Server.Mono/FFMpeg/FFMpegDownloader.cs create mode 100644 MediaBrowser.Server.Mono/Native/Assemblies.cs create mode 100644 MediaBrowser.Server.Mono/Native/Autorun.cs create mode 100644 MediaBrowser.Server.Mono/Native/HttpMessageHandlerFactory.cs create mode 100644 MediaBrowser.Server.Mono/Native/NativeApp.cs create mode 100644 MediaBrowser.Server.Mono/Native/ServerAuthorization.cs create mode 100644 MediaBrowser.Server.Mono/Native/Sqlite.cs delete mode 100644 MediaBrowser.ServerApplication/EntryPoints/UdpServerEntryPoint.cs create mode 100644 MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs create mode 100644 MediaBrowser.ServerApplication/FFMpeg/FFMpegInfo.cs create mode 100644 MediaBrowser.ServerApplication/FFMpeg/ffmpeg-20130904-git-f974289-win32-static.7z.REMOVED.git-id delete mode 100644 MediaBrowser.ServerApplication/Implementations/FFMpegDownloader.cs delete mode 100644 MediaBrowser.ServerApplication/Implementations/ZipClient.cs delete mode 100644 MediaBrowser.ServerApplication/Implementations/ffmpeg-20130904-git-f974289-win32-static.7z.REMOVED.git-id create mode 100644 MediaBrowser.ServerApplication/Native/Assemblies.cs create mode 100644 MediaBrowser.ServerApplication/Native/Autorun.cs create mode 100644 MediaBrowser.ServerApplication/Native/BrowserLauncher.cs create mode 100644 MediaBrowser.ServerApplication/Native/HttpMessageHandlerFactory.cs create mode 100644 MediaBrowser.ServerApplication/Native/NativeApp.cs create mode 100644 MediaBrowser.ServerApplication/Native/RegisterServer.bat create mode 100644 MediaBrowser.ServerApplication/Native/ServerAuthorization.cs create mode 100644 MediaBrowser.ServerApplication/Native/Sqlite.cs delete mode 100644 MediaBrowser.ServerApplication/RegisterServer.bat (limited to 'MediaBrowser.ServerApplication/ApplicationHost.cs') diff --git a/MediaBrowser.Common.Implementations/Archiving/ZipClient.cs b/MediaBrowser.Common.Implementations/Archiving/ZipClient.cs new file mode 100644 index 000000000..39690eb07 --- /dev/null +++ b/MediaBrowser.Common.Implementations/Archiving/ZipClient.cs @@ -0,0 +1,87 @@ +using MediaBrowser.Model.IO; +using SharpCompress.Archive.SevenZip; +using SharpCompress.Common; +using SharpCompress.Reader; +using System.IO; + +namespace MediaBrowser.Common.Implementations.Archiving +{ + /// + /// Class DotNetZipClient + /// + public class ZipClient : IZipClient + { + /// + /// Extracts all. + /// + /// The source file. + /// The target path. + /// if set to true [overwrite existing files]. + public void ExtractAll(string sourceFile, string targetPath, bool overwriteExistingFiles) + { + using (var fileStream = File.OpenRead(sourceFile)) + { + ExtractAll(fileStream, targetPath, overwriteExistingFiles); + } + } + + /// + /// Extracts all. + /// + /// The source. + /// The target path. + /// if set to true [overwrite existing files]. + public void ExtractAll(Stream source, string targetPath, bool overwriteExistingFiles) + { + using (var reader = ReaderFactory.Open(source)) + { + var options = ExtractOptions.ExtractFullPath; + + if (overwriteExistingFiles) + { + options = options | ExtractOptions.Overwrite; + } + + reader.WriteAllToDirectory(targetPath, options); + } + } + + /// + /// Extracts all from7z. + /// + /// The source file. + /// The target path. + /// if set to true [overwrite existing files]. + public void ExtractAllFrom7z(string sourceFile, string targetPath, bool overwriteExistingFiles) + { + using (var fileStream = File.OpenRead(sourceFile)) + { + ExtractAllFrom7z(fileStream, targetPath, overwriteExistingFiles); + } + } + + /// + /// Extracts all from7z. + /// + /// The source. + /// The target path. + /// if set to true [overwrite existing files]. + public void ExtractAllFrom7z(Stream source, string targetPath, bool overwriteExistingFiles) + { + using (var archive = SevenZipArchive.Open(source)) + { + using (var reader = archive.ExtractAllEntries()) + { + var options = ExtractOptions.ExtractFullPath; + + if (overwriteExistingFiles) + { + options = options | ExtractOptions.Overwrite; + } + + reader.WriteAllToDirectory(targetPath, options); + } + } + } + } +} diff --git a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs index c0ac6a4b3..0d96df9a2 100644 --- a/MediaBrowser.Common.Implementations/BaseApplicationHost.cs +++ b/MediaBrowser.Common.Implementations/BaseApplicationHost.cs @@ -1,5 +1,6 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Events; +using MediaBrowser.Common.Implementations.Archiving; using MediaBrowser.Common.Implementations.NetworkManagement; using MediaBrowser.Common.Implementations.ScheduledTasks; using MediaBrowser.Common.Implementations.Security; @@ -10,6 +11,7 @@ using MediaBrowser.Common.Plugins; using MediaBrowser.Common.ScheduledTasks; using MediaBrowser.Common.Security; using MediaBrowser.Common.Updates; +using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Updates; @@ -149,6 +151,12 @@ namespace MediaBrowser.Common.Implementations /// The installation manager. protected IInstallationManager InstallationManager { get; set; } + /// + /// Gets or sets the zip client. + /// + /// The zip client. + protected IZipClient ZipClient { get; set; } + /// /// Initializes a new instance of the class. /// @@ -202,12 +210,27 @@ namespace MediaBrowser.Common.Implementations { Resolve().AddTasks(GetExports(false)); - Task.Run(() => ConfigureAutoRunAtStartup()); + Task.Run(() => ConfigureAutorun()); ConfigurationManager.ConfigurationUpdated += OnConfigurationUpdated; }); } + /// + /// Configures the autorun. + /// + private void ConfigureAutorun() + { + try + { + ConfigureAutoRunAtStartup(ConfigurationManager.CommonConfiguration.RunAtStartup); + } + catch (Exception ex) + { + Logger.ErrorException("Error configuring autorun", ex); + } + } + /// /// Gets the composable part assemblies. /// @@ -281,6 +304,9 @@ namespace MediaBrowser.Common.Implementations InstallationManager = new InstallationManager(Logger, this, ApplicationPaths, HttpClient, JsonSerializer, SecurityManager, NetworkManager, ConfigurationManager); RegisterSingleInstance(InstallationManager); + + ZipClient = new ZipClient(); + RegisterSingleInstance(ZipClient); }); } @@ -453,11 +479,6 @@ namespace MediaBrowser.Common.Implementations } } - /// - /// Defines the full path to our shortcut in the start menu - /// - protected abstract string ProductShortcutPath { get; } - /// /// Handles the ConfigurationUpdated event of the ConfigurationManager control. /// @@ -466,32 +487,10 @@ namespace MediaBrowser.Common.Implementations /// protected virtual void OnConfigurationUpdated(object sender, EventArgs e) { - ConfigureAutoRunAtStartup(); + ConfigureAutorun(); } - /// - /// Configures the auto run at startup. - /// - private void ConfigureAutoRunAtStartup() - { - if (ConfigurationManager.CommonConfiguration.RunAtStartup) - { - //Copy our shortut into the startup folder for this user - File.Copy(ProductShortcutPath, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Startup), Path.GetFileName(ProductShortcutPath) ?? "MBstartup.lnk"), true); - } - else - { - //Remove our shortcut from the startup folder for this user - try - { - File.Delete(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Startup), Path.GetFileName(ProductShortcutPath) ?? "MBstartup.lnk")); - } - catch (FileNotFoundException) - { - //This is okay - trying to remove it anyway - } - } - } + protected abstract void ConfigureAutoRunAtStartup(bool autorun); /// /// Removes the plugin. diff --git a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj index 79514b5cb..11da950f7 100644 --- a/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj +++ b/MediaBrowser.Common.Implementations/MediaBrowser.Common.Implementations.csproj @@ -37,6 +37,9 @@ Always + + ..\packages\sharpcompress.0.10.1.3\lib\net40\SharpCompress.dll + @@ -58,6 +61,7 @@ Properties\SharedVersion.cs + diff --git a/MediaBrowser.Common.Implementations/packages.config b/MediaBrowser.Common.Implementations/packages.config index 4be861cce..d03cb14e0 100644 --- a/MediaBrowser.Common.Implementations/packages.config +++ b/MediaBrowser.Common.Implementations/packages.config @@ -2,5 +2,6 @@ + \ No newline at end of file diff --git a/MediaBrowser.Model/IO/IZipClient.cs b/MediaBrowser.Model/IO/IZipClient.cs index c9e7e0db6..694c393aa 100644 --- a/MediaBrowser.Model/IO/IZipClient.cs +++ b/MediaBrowser.Model/IO/IZipClient.cs @@ -22,5 +22,21 @@ namespace MediaBrowser.Model.IO /// The target path. /// if set to true [overwrite existing files]. void ExtractAll(Stream source, string targetPath, bool overwriteExistingFiles); + + /// + /// Extracts all from7z. + /// + /// The source file. + /// The target path. + /// if set to true [overwrite existing files]. + void ExtractAllFrom7z(string sourceFile, string targetPath, bool overwriteExistingFiles); + + /// + /// Extracts all from7z. + /// + /// The source. + /// The target path. + /// if set to true [overwrite existing files]. + void ExtractAllFrom7z(Stream source, string targetPath, bool overwriteExistingFiles); } } diff --git a/MediaBrowser.Mono.userprefs b/MediaBrowser.Mono.userprefs index 95fb57a89..80da5915d 100644 --- a/MediaBrowser.Mono.userprefs +++ b/MediaBrowser.Mono.userprefs @@ -1,6 +1,17 @@  - + + + + + + + + + + + + diff --git a/MediaBrowser.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs b/MediaBrowser.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs new file mode 100644 index 000000000..9c1a953b1 --- /dev/null +++ b/MediaBrowser.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs @@ -0,0 +1,97 @@ +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.Server.Implementations.EntryPoints +{ + /// + /// Class UdpServerEntryPoint + /// + public class UdpServerEntryPoint : IServerEntryPoint + { + /// + /// Gets or sets the UDP server. + /// + /// The UDP server. + private UdpServer UdpServer { get; set; } + + /// + /// The _logger + /// + private readonly ILogger _logger; + /// + /// The _network manager + /// + private readonly INetworkManager _networkManager; + /// + /// The _server configuration manager + /// + private readonly IServerConfigurationManager _serverConfigurationManager; + /// + /// The _HTTP server + /// + private readonly IHttpServer _httpServer; + + public const int PortNumber = 7359; + + /// + /// Initializes a new instance of the class. + /// + /// The logger. + /// The network manager. + /// The server configuration manager. + /// The HTTP server. + public UdpServerEntryPoint(ILogger logger, INetworkManager networkManager, IServerConfigurationManager serverConfigurationManager, IHttpServer httpServer) + { + _logger = logger; + _networkManager = networkManager; + _serverConfigurationManager = serverConfigurationManager; + _httpServer = httpServer; + } + + /// + /// Runs this instance. + /// + public void Run() + { + var udpServer = new UdpServer(_logger, _networkManager, _serverConfigurationManager, _httpServer); + + try + { + udpServer.Start(PortNumber); + + UdpServer = udpServer; + } + catch (SocketException ex) + { + _logger.ErrorException("Failed to start UDP Server", ex); + } + } + + /// + /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + /// + public void Dispose() + { + Dispose(true); + } + + /// + /// Releases unmanaged and - optionally - managed resources. + /// + /// true to release both managed and unmanaged resources; false to release only unmanaged resources. + protected virtual void Dispose(bool dispose) + { + if (dispose) + { + if (UdpServer != null) + { + UdpServer.Dispose(); + } + } + } + } +} diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index e44089cc1..f409b7205 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -113,6 +113,7 @@ + diff --git a/MediaBrowser.Server.Mono/FFMpeg/FFMpegDownloader.cs b/MediaBrowser.Server.Mono/FFMpeg/FFMpegDownloader.cs new file mode 100644 index 000000000..cc268ef07 --- /dev/null +++ b/MediaBrowser.Server.Mono/FFMpeg/FFMpegDownloader.cs @@ -0,0 +1,36 @@ +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.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; + + public FFMpegDownloader(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IZipClient zipClient) + { + _logger = logger; + _appPaths = appPaths; + _httpClient = httpClient; + _zipClient = zipClient; + } + + public Task GetFFMpegInfo() + { + return Task.FromResult (new FFMpegInfo()); + } + } +} diff --git a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj index a97ab4fac..1c369daac 100644 --- a/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj +++ b/MediaBrowser.Server.Mono/MediaBrowser.Server.Mono.csproj @@ -40,6 +40,9 @@ + + + @@ -52,6 +55,25 @@ + + EntryPoints\StartupWizard.cs + + + Native\BrowserLauncher.cs + + + + + + FFMpeg\FFMpegInfo.cs + + + ApplicationHost.cs + + + + + @@ -88,4 +110,10 @@ MediaBrowser.Api + + + + + + \ No newline at end of file diff --git a/MediaBrowser.Server.Mono/Native/Assemblies.cs b/MediaBrowser.Server.Mono/Native/Assemblies.cs new file mode 100644 index 000000000..eae6366e1 --- /dev/null +++ b/MediaBrowser.Server.Mono/Native/Assemblies.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using System.Reflection; + +namespace MediaBrowser.ServerApplication.Native +{ + /// + /// Class Assemblies + /// + public static class Assemblies + { + /// + /// Gets the assemblies with parts. + /// + /// List{Assembly}. + public static List GetAssembliesWithParts() + { + var list = new List(); + + return list; + } + } +} diff --git a/MediaBrowser.Server.Mono/Native/Autorun.cs b/MediaBrowser.Server.Mono/Native/Autorun.cs new file mode 100644 index 000000000..ee33c5967 --- /dev/null +++ b/MediaBrowser.Server.Mono/Native/Autorun.cs @@ -0,0 +1,20 @@ +using System; +using System.IO; + +namespace MediaBrowser.ServerApplication.Native +{ + /// + /// Class Autorun + /// + public static class Autorun + { + /// + /// Configures the specified autorun. + /// + /// if set to true [autorun]. + public static void Configure(bool autorun) + { + + } + } +} diff --git a/MediaBrowser.Server.Mono/Native/HttpMessageHandlerFactory.cs b/MediaBrowser.Server.Mono/Native/HttpMessageHandlerFactory.cs new file mode 100644 index 000000000..5823a7e51 --- /dev/null +++ b/MediaBrowser.Server.Mono/Native/HttpMessageHandlerFactory.cs @@ -0,0 +1,25 @@ +using System.Net; +using System.Net.Cache; +using System.Net.Http; + +namespace MediaBrowser.ServerApplication.Native +{ + /// + /// Class HttpMessageHandlerFactory + /// + public static class HttpMessageHandlerFactory + { + /// + /// Gets the HTTP message handler. + /// + /// if set to true [enable HTTP compression]. + /// HttpMessageHandler. + public static HttpMessageHandler GetHttpMessageHandler(bool enableHttpCompression) + { + return new HttpClientHandler + { + AutomaticDecompression = enableHttpCompression ? DecompressionMethods.Deflate : DecompressionMethods.None + }; + } + } +} diff --git a/MediaBrowser.Server.Mono/Native/NativeApp.cs b/MediaBrowser.Server.Mono/Native/NativeApp.cs new file mode 100644 index 000000000..bb47f6ea4 --- /dev/null +++ b/MediaBrowser.Server.Mono/Native/NativeApp.cs @@ -0,0 +1,25 @@ + +namespace MediaBrowser.ServerApplication.Native +{ + /// + /// Class NativeApp + /// + public static class NativeApp + { + /// + /// Shutdowns this instance. + /// + public static void Shutdown() + { + + } + + /// + /// Restarts this instance. + /// + public static void Restart() + { + + } + } +} diff --git a/MediaBrowser.Server.Mono/Native/ServerAuthorization.cs b/MediaBrowser.Server.Mono/Native/ServerAuthorization.cs new file mode 100644 index 000000000..6f43a12c0 --- /dev/null +++ b/MediaBrowser.Server.Mono/Native/ServerAuthorization.cs @@ -0,0 +1,26 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Reflection; + +namespace MediaBrowser.ServerApplication.Native +{ + /// + /// Class Authorization + /// + public static class ServerAuthorization + { + /// + /// Authorizes the server. + /// + /// The HTTP server port. + /// The HTTP server URL prefix. + /// The web socket port. + /// The UDP port. + /// The temp directory. + public static void AuthorizeServer(int httpServerPort, string httpServerUrlPrefix, int webSocketPort, int udpPort, string tempDirectory) + { + + } + } +} diff --git a/MediaBrowser.Server.Mono/Native/Sqlite.cs b/MediaBrowser.Server.Mono/Native/Sqlite.cs new file mode 100644 index 000000000..cc20952d7 --- /dev/null +++ b/MediaBrowser.Server.Mono/Native/Sqlite.cs @@ -0,0 +1,36 @@ +using System.Data; +using System.Data.SQLite; +using System.Threading.Tasks; + +namespace MediaBrowser.ServerApplication.Native +{ + /// + /// Class Sqlite + /// + public static class Sqlite + { + /// + /// Connects to db. + /// + /// The db path. + /// Task{IDbConnection}. + /// dbPath + public static async Task 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.Server.Mono/gtk-gui/gui.stetic b/MediaBrowser.Server.Mono/gtk-gui/gui.stetic index d564b4446..81685442c 100644 --- a/MediaBrowser.Server.Mono/gtk-gui/gui.stetic +++ b/MediaBrowser.Server.Mono/gtk-gui/gui.stetic @@ -1,6 +1,7 @@  + .. 2.12 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); } - - /// - /// Opens the dashboard page. - /// - /// The page. - /// The logged in user. - /// The configuration manager. - /// The app host. - 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); - } - - /// - /// Opens the URL. - /// - /// The URL. - 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."); - } - } - - /// - /// Processes the exited. - /// - /// The sender. - /// The instance containing the event data. - static void ProcessExited(object sender, EventArgs e) - { - ((Process)sender).Dispose(); - } } } diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index e96516603..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 /// public class ApplicationHost : BaseApplicationHost, IServerApplicationHost { - internal const int UdpServerPort = 7359; - /// /// Gets the server kernel. /// @@ -142,11 +138,6 @@ namespace MediaBrowser.ServerApplication /// The provider manager. private IProviderManager ProviderManager { get; set; } /// - /// Gets or sets the zip client. - /// - /// The zip client. - private IZipClient ZipClient { get; set; } - /// /// Gets or sets the HTTP server. /// /// The HTTP server. @@ -175,14 +166,6 @@ namespace MediaBrowser.ServerApplication private IItemRepository ItemRepository { get; set; } private INotificationsRepository NotificationsRepository { get; set; } - /// - /// The full path to our startmenu shortcut - /// - protected override string ProductShortcutPath - { - get { return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu), "Media Browser 3", "Media Browser Server.lnk"); } - } - private Task _httpServerCreationTask; /// @@ -256,9 +239,6 @@ namespace MediaBrowser.ServerApplication RegisterSingleInstance(() => new BdInfoExaminer()); - ZipClient = new ZipClient(); - RegisterSingleInstance(ZipClient); - var mediaEncoderTask = RegisterMediaEncoder(); UserDataRepository = new SqliteUserDataRepository(ApplicationPaths, JsonSerializer, LogManager); @@ -322,7 +302,7 @@ namespace MediaBrowser.ServerApplication /// Task. private async Task RegisterMediaEncoder() { - var info = await new FFMpegDownloader(Logger, ApplicationPaths, HttpClient).GetFFMpegInfo().ConfigureAwait(false); + var info = await new FFMpegDownloader(Logger, ApplicationPaths, HttpClient, ZipClient).GetFFMpegInfo().ConfigureAwait(false); MediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), ApplicationPaths, JsonSerializer, info.Path, info.ProbePath, info.Version); RegisterSingleInstance(MediaEncoder); @@ -407,27 +387,14 @@ namespace MediaBrowser.ServerApplication /// The db path. /// Task{IDbConnection}. /// dbPath - private static async Task ConnectToDb(string dbPath) + private static Task 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); } /// @@ -479,7 +446,7 @@ namespace MediaBrowser.ServerApplication IsoManager.AddParts(GetExports()); SessionManager.AddParts(GetExports()); - + ImageProcessor.AddParts(GetExports()); } @@ -530,7 +497,6 @@ namespace MediaBrowser.ServerApplication { NotifyPendingRestart(); } - } /// @@ -547,7 +513,7 @@ namespace MediaBrowser.ServerApplication Logger.ErrorException("Error sending server restart web socket message", ex); } - MainStartup.Restart(); + NativeApp.Restart(); } /// @@ -571,44 +537,44 @@ namespace MediaBrowser.ServerApplication /// IEnumerable{Assembly}. protected override IEnumerable 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(); @@ -667,7 +633,7 @@ namespace MediaBrowser.ServerApplication Logger.ErrorException("Error sending server shutdown web socket message", ex); } - MainStartup.Shutdown(); + NativeApp.Shutdown(); } /// @@ -677,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); } } @@ -716,8 +662,7 @@ namespace MediaBrowser.ServerApplication /// The cancellation token. /// The progress. /// Task{CheckForUpdateResult}. - public override async Task CheckForApplicationUpdate(CancellationToken cancellationToken, - IProgress progress) + public override async Task CheckForApplicationUpdate(CancellationToken cancellationToken, IProgress progress) { var availablePackages = await InstallationManager.GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false); @@ -748,11 +693,12 @@ namespace MediaBrowser.ServerApplication /// HttpMessageHandler. 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 /// /// The app host. /// The user manager. - 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 -{ - /// - /// Class UdpServerEntryPoint - /// - public class UdpServerEntryPoint : IServerEntryPoint - { - /// - /// Gets or sets the UDP server. - /// - /// The UDP server. - private UdpServer UdpServer { get; set; } - - /// - /// The _logger - /// - private readonly ILogger _logger; - /// - /// The _network manager - /// - private readonly INetworkManager _networkManager; - /// - /// The _server configuration manager - /// - private readonly IServerConfigurationManager _serverConfigurationManager; - /// - /// The _HTTP server - /// - private readonly IHttpServer _httpServer; - - /// - /// Initializes a new instance of the class. - /// - /// The logger. - /// The network manager. - /// The server configuration manager. - /// The HTTP server. - public UdpServerEntryPoint(ILogger logger, INetworkManager networkManager, IServerConfigurationManager serverConfigurationManager, IHttpServer httpServer) - { - _logger = logger; - _networkManager = networkManager; - _serverConfigurationManager = serverConfigurationManager; - _httpServer = httpServer; - } - - /// - /// Runs this instance. - /// - 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); - } - } - - /// - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// - public void Dispose() - { - Dispose(true); - } - - /// - /// Releases unmanaged and - optionally - managed resources. - /// - /// true to release both managed and unmanaged resources; false to release only unmanaged resources. - 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..c43a85c87 --- /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://raw.github.com/MediaBrowser/MediaBrowser/master/MediaBrowser.ServerApplication/Implementations/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 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(); + + 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 DownloadFFMpeg(FFMpegInfo info, string url) + { + return _httpClient.GetTempFile(new HttpRequestOptions + { + Url = url, + CancellationToken = CancellationToken.None, + Progress = new Progress(), + + // 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); + } + } + + /// + /// Extracts the fonts. + /// + /// The target path. + 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); + } + } + + /// + /// Downloads the font file. + /// + /// The fonts directory. + /// The font filename. + /// Task. + 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() + + }).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); + } + } + + /// + /// Writes the font config file. + /// + /// The fonts directory. + /// Task. + 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("{0}ArialArial Unicode MS", 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); + } + } + } + + /// + /// Gets the media tools path. + /// + /// if set to true [create]. + /// System.String. + 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 +{ + /// + /// Class FFMpegInfo + /// + public class FFMpegInfo + { + /// + /// Gets or sets the path. + /// + /// The path. + public string Path { get; set; } + /// + /// Gets or sets the probe path. + /// + /// The probe path. + public string ProbePath { get; set; } + /// + /// Gets or sets the version. + /// + /// The version. + 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/FFMpegDownloader.cs b/MediaBrowser.ServerApplication/Implementations/FFMpegDownloader.cs deleted file mode 100644 index 1bc0b90f0..000000000 --- a/MediaBrowser.ServerApplication/Implementations/FFMpegDownloader.cs +++ /dev/null @@ -1,315 +0,0 @@ -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.IO; -using MediaBrowser.Common.Net; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Net; -using SharpCompress.Archive.SevenZip; -using SharpCompress.Common; -using SharpCompress.Reader; -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.Implementations -{ - public class FFMpegDownloader - { - private readonly IHttpClient _httpClient; - private readonly IApplicationPaths _appPaths; - private readonly ILogger _logger; - - 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://raw.github.com/MediaBrowser/MediaBrowser/master/MediaBrowser.ServerApplication/Implementations/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) - { - _logger = logger; - _appPaths = appPaths; - _httpClient = httpClient; - } - - public async Task 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(); - - 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 DownloadFFMpeg(FFMpegInfo info, string url) - { - return _httpClient.GetTempFile(new HttpRequestOptions - { - Url = url, - CancellationToken = CancellationToken.None, - Progress = new Progress(), - - // 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) - { - using (var archive = SevenZipArchive.Open(archivePath)) - { - using (var reader = archive.ExtractAllEntries()) - { - reader.WriteAllToDirectory(targetPath, ExtractOptions.ExtractFullPath | ExtractOptions.Overwrite); - } - } - } - - private void DeleteFile(string path) - { - try - { - File.Delete(path); - } - catch (IOException ex) - { - _logger.ErrorException("Error deleting temp file {0}", ex, path); - } - } - - /// - /// Extracts the fonts. - /// - /// The target path. - 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); - } - } - - /// - /// Downloads the font file. - /// - /// The fonts directory. - /// The font filename. - /// Task. - 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() - - }).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); - } - } - - /// - /// Writes the font config file. - /// - /// The fonts directory. - /// Task. - 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("{0}ArialArial Unicode MS", 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); - } - } - } - - /// - /// Gets the media tools path. - /// - /// if set to true [create]. - /// System.String. - 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/ZipClient.cs b/MediaBrowser.ServerApplication/Implementations/ZipClient.cs deleted file mode 100644 index e9e8645e9..000000000 --- a/MediaBrowser.ServerApplication/Implementations/ZipClient.cs +++ /dev/null @@ -1,48 +0,0 @@ -using MediaBrowser.Model.IO; -using SharpCompress.Common; -using SharpCompress.Reader; -using System.IO; - -namespace MediaBrowser.ServerApplication.Implementations -{ - /// - /// Class DotNetZipClient - /// - public class ZipClient : IZipClient - { - /// - /// Extracts all. - /// - /// The source file. - /// The target path. - /// if set to true [overwrite existing files]. - public void ExtractAll(string sourceFile, string targetPath, bool overwriteExistingFiles) - { - using (var fileStream = File.OpenRead(sourceFile)) - { - ExtractAll(fileStream, targetPath, overwriteExistingFiles); - } - } - - /// - /// Extracts all. - /// - /// The source. - /// The target path. - /// if set to true [overwrite existing files]. - public void ExtractAll(Stream source, string targetPath, bool overwriteExistingFiles) - { - using (var reader = ReaderFactory.Open(source)) - { - var options = ExtractOptions.ExtractFullPath; - - if (overwriteExistingFiles) - { - options = options | ExtractOptions.Overwrite; - } - - reader.WriteAllToDirectory(targetPath, options); - } - } - } -} diff --git a/MediaBrowser.ServerApplication/Implementations/ffmpeg-20130904-git-f974289-win32-static.7z.REMOVED.git-id b/MediaBrowser.ServerApplication/Implementations/ffmpeg-20130904-git-f974289-win32-static.7z.REMOVED.git-id deleted file mode 100644 index 9f83b949b..000000000 --- a/MediaBrowser.ServerApplication/Implementations/ffmpeg-20130904-git-f974289-win32-static.7z.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -8f1dfd62d31e48c31bef4b9ccc0e514f46650a79 \ 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 /// The instance containing the event data. 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); } /// @@ -254,7 +255,7 @@ namespace MediaBrowser.ServerApplication /// private void OpenDashboard(User loggedInUser) { - App.OpenDashboardPage("dashboard.html", loggedInUser, _configurationManager, _appHost); + BrowserLauncher.OpenDashboardPage("dashboard.html", loggedInUser, _configurationManager, _appHost, _logger); } /// @@ -264,7 +265,7 @@ namespace MediaBrowser.ServerApplication /// The instance containing the event data. private void cmVisitCT_click(object sender, RoutedEventArgs e) { - App.OpenUrl("http://community.mediabrowser.tv/"); + BrowserLauncher.OpenUrl("http://community.mediabrowser.tv/", _logger); } /// @@ -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); } /// diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 793489c1f..61ec19dd5 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -130,10 +130,6 @@ False ..\packages\MediaBrowser.IsoMounting.3.0.56\lib\net45\MediaBrowser.IsoMounter.dll - - False - ..\packages\morelinq.1.0.16006\lib\net35\MoreLinq.dll - False ..\packages\NLog.2.0.1.2\lib\net45\NLog.dll @@ -168,9 +164,6 @@ False ..\packages\ServiceStack.Text.3.9.62\lib\net35\ServiceStack.Text.dll - - ..\packages\sharpcompress.0.10.1.3\lib\net40\SharpCompress.dll - False ..\packages\SimpleInjector.2.3.5\lib\net40-client\SimpleInjector.dll @@ -190,7 +183,6 @@ - @@ -212,12 +204,19 @@ Component - - + + + + + + + + Component + SplashWindow.xaml @@ -245,7 +244,6 @@ Code - LibraryExplorer.xaml @@ -281,15 +279,15 @@ Resources.Designer.cs - - + + SettingsSingleFileGenerator Settings.Designer.cs - + 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 +{ + /// + /// Class Assemblies + /// + public static class Assemblies + { + /// + /// Gets the assemblies with parts. + /// + /// List{Assembly}. + public static List GetAssembliesWithParts() + { + var list = new List(); + + 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 +{ + /// + /// Class Autorun + /// + public static class Autorun + { + /// + /// Configures the specified autorun. + /// + /// if set to true [autorun]. + 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 + { + /// + /// Opens the dashboard page. + /// + /// The page. + /// The logged in user. + /// The configuration manager. + /// The app host. + 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); + } + + /// + /// Opens the URL. + /// + /// The URL. + 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."); + } + } + + /// + /// Processes the exited. + /// + /// The sender. + /// The instance containing the event data. + 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 +{ + /// + /// Class HttpMessageHandlerFactory + /// + public static class HttpMessageHandlerFactory + { + /// + /// Gets the HTTP message handler. + /// + /// if set to true [enable HTTP compression]. + /// HttpMessageHandler. + 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 +{ + /// + /// Class NativeApp + /// + public static class NativeApp + { + /// + /// Shutdowns this instance. + /// + public static void Shutdown() + { + MainStartup.Shutdown(); + } + + /// + /// Restarts this instance. + /// + public static void Restart() + { + MainStartup.Restart(); + } + } +} diff --git a/MediaBrowser.ServerApplication/Native/RegisterServer.bat b/MediaBrowser.ServerApplication/Native/RegisterServer.bat new file mode 100644 index 000000000..d762dfaf7 --- /dev/null +++ b/MediaBrowser.ServerApplication/Native/RegisterServer.bat @@ -0,0 +1,28 @@ +rem %1 = http server port +rem %2 = http server url +rem %3 = udp server port +rem %4 = tcp server port (web socket) + +if [%1]==[] GOTO DONE + +netsh advfirewall firewall delete rule name="Port %1" protocol=TCP localport=%1 +netsh advfirewall firewall add rule name="Port %1" dir=in action=allow protocol=TCP localport=%1 + +if [%2]==[] GOTO DONE + +netsh http del urlacl url="%2" user="NT AUTHORITY\Authenticated Users" +netsh http add urlacl url="%2" user="NT AUTHORITY\Authenticated Users" + +if [%3]==[] GOTO DONE + +netsh advfirewall firewall delete rule name="Port %3" protocol=UDP localport=%3 +netsh advfirewall firewall add rule name="Port %3" dir=in action=allow protocol=UDP localport=%3 + +if [%4]==[] GOTO DONE + +netsh advfirewall firewall delete rule name="Port %4" protocol=TCP localport=%4 +netsh advfirewall firewall add rule name="Port %4" dir=in action=allow protocol=TCP localport=%4 + + +:DONE +Exit \ No newline at end of file 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 +{ + /// + /// Class Authorization + /// + public static class ServerAuthorization + { + /// + /// Authorizes the server. + /// + /// The HTTP server port. + /// The HTTP server URL prefix. + /// The web socket port. + /// The UDP port. + /// The temp directory. + 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 +{ + /// + /// Class Sqlite + /// + public static class Sqlite + { + /// + /// Connects to db. + /// + /// The db path. + /// Task{IDbConnection}. + /// dbPath + public static async Task 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/RegisterServer.bat b/MediaBrowser.ServerApplication/RegisterServer.bat deleted file mode 100644 index d762dfaf7..000000000 --- a/MediaBrowser.ServerApplication/RegisterServer.bat +++ /dev/null @@ -1,28 +0,0 @@ -rem %1 = http server port -rem %2 = http server url -rem %3 = udp server port -rem %4 = tcp server port (web socket) - -if [%1]==[] GOTO DONE - -netsh advfirewall firewall delete rule name="Port %1" protocol=TCP localport=%1 -netsh advfirewall firewall add rule name="Port %1" dir=in action=allow protocol=TCP localport=%1 - -if [%2]==[] GOTO DONE - -netsh http del urlacl url="%2" user="NT AUTHORITY\Authenticated Users" -netsh http add urlacl url="%2" user="NT AUTHORITY\Authenticated Users" - -if [%3]==[] GOTO DONE - -netsh advfirewall firewall delete rule name="Port %3" protocol=UDP localport=%3 -netsh advfirewall firewall add rule name="Port %3" dir=in action=allow protocol=UDP localport=%3 - -if [%4]==[] GOTO DONE - -netsh advfirewall firewall delete rule name="Port %4" protocol=TCP localport=%4 -netsh advfirewall firewall add rule name="Port %4" dir=in action=allow protocol=TCP localport=%4 - - -:DONE -Exit \ No newline at end of file diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config index 137483ef1..e680b556f 100644 --- a/MediaBrowser.ServerApplication/packages.config +++ b/MediaBrowser.ServerApplication/packages.config @@ -4,14 +4,12 @@ - - \ No newline at end of file -- cgit v1.2.3