diff options
| author | Eric Reed <ebr@mediabrowser3.com> | 2013-09-23 12:28:44 -0400 |
|---|---|---|
| committer | Eric Reed <ebr@mediabrowser3.com> | 2013-09-23 12:28:44 -0400 |
| commit | c6e57c6448c04998bcae5a906e7a064300542e75 (patch) | |
| tree | 548e46418f25b2dc65b78c1a96083c5ca2b9c81a /MediaBrowser.ServerApplication | |
| parent | d9fecd78a54453a7656f649a6fcfc654f74dbdf6 (diff) | |
| parent | cacba5ca11d600ed9d496c566807be92b228de7e (diff) | |
Merge branch 'master' of https://github.com/MediaBrowser/MediaBrowser
Diffstat (limited to 'MediaBrowser.ServerApplication')
6 files changed, 242 insertions, 16 deletions
diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index 471525816..5cae99785 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -60,7 +60,6 @@ using System.Net.Http; using System.Reflection; using System.Threading; using System.Threading.Tasks; -using System.Windows; namespace MediaBrowser.ServerApplication { @@ -285,8 +284,7 @@ namespace MediaBrowser.ServerApplication RegisterSingleInstance<ILibrarySearchEngine>(() => new LuceneSearchEngine(ApplicationPaths, LogManager, LibraryManager)); - MediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), ZipClient, ApplicationPaths, JsonSerializer, HttpClient); - RegisterSingleInstance(MediaEncoder); + await RegisterMediaEncoder().ConfigureAwait(false); var clientConnectionManager = new SessionManager(UserDataRepository, ServerConfigurationManager, Logger, UserRepository); RegisterSingleInstance<ISessionManager>(clientConnectionManager); @@ -318,6 +316,18 @@ namespace MediaBrowser.ServerApplication } /// <summary> + /// Registers the media encoder. + /// </summary> + /// <returns>Task.</returns> + private async Task RegisterMediaEncoder() + { + 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); + } + + /// <summary> /// Sets the kernel properties. /// </summary> private void SetKernelProperties() @@ -708,7 +718,7 @@ namespace MediaBrowser.ServerApplication { var availablePackages = await InstallationManager.GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false); - var version = InstallationManager.GetLatestCompatibleVersion(availablePackages, Constants.MbServerPkgName, ConfigurationManager.CommonConfiguration.SystemUpdateLevel); + var version = InstallationManager.GetLatestCompatibleVersion(availablePackages, Constants.MbServerPkgName, ApplicationVersion, ConfigurationManager.CommonConfiguration.SystemUpdateLevel); return version != null ? new CheckForUpdateResult { AvailableVersion = version.version, IsUpdateAvailable = version.version > ApplicationVersion, Package = version } : new CheckForUpdateResult { AvailableVersion = ApplicationVersion, IsUpdateAvailable = false }; diff --git a/MediaBrowser.ServerApplication/Implementations/FFMpegDownloader.cs b/MediaBrowser.ServerApplication/Implementations/FFMpegDownloader.cs new file mode 100644 index 000000000..7fd0acddd --- /dev/null +++ b/MediaBrowser.ServerApplication/Implementations/FFMpegDownloader.cs @@ -0,0 +1,205 @@ +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.IO; +using MediaBrowser.Common.Net; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Logging; +using System; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace MediaBrowser.ServerApplication.Implementations +{ + public class FFMpegDownloader + { + private readonly IZipClient _zipClient; + private readonly IHttpClient _httpClient; + private readonly IApplicationPaths _appPaths; + private readonly ILogger _logger; + + public FFMpegDownloader(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IZipClient zipClient) + { + _logger = logger; + _appPaths = appPaths; + _httpClient = httpClient; + _zipClient = zipClient; + } + + public async Task<FFMpegInfo> GetFFMpegInfo() + { + var assembly = GetType().Assembly; + + var prefix = GetType().Namespace + "."; + + var srch = prefix + "ffmpeg"; + + var resource = assembly.GetManifestResourceNames().First(r => r.StartsWith(srch)); + + var filename = + resource.Substring(resource.IndexOf(prefix, StringComparison.OrdinalIgnoreCase) + prefix.Length); + + var versionedDirectoryPath = Path.Combine(GetMediaToolsPath(true), + Path.GetFileNameWithoutExtension(filename)); + + if (!Directory.Exists(versionedDirectoryPath)) + { + Directory.CreateDirectory(versionedDirectoryPath); + } + + await ExtractTools(assembly, resource, versionedDirectoryPath).ConfigureAwait(false); + + return new FFMpegInfo + { + ProbePath = Path.Combine(versionedDirectoryPath, "ffprobe.exe"), + Path = Path.Combine(versionedDirectoryPath, "ffmpeg.exe"), + Version = Path.GetFileNameWithoutExtension(versionedDirectoryPath) + }; + } + + /// <summary> + /// Extracts the tools. + /// </summary> + /// <param name="assembly">The assembly.</param> + /// <param name="zipFileResourcePath">The zip file resource path.</param> + /// <param name="targetPath">The target path.</param> + private async Task ExtractTools(Assembly assembly, string zipFileResourcePath, string targetPath) + { + using (var resourceStream = assembly.GetManifestResourceStream(zipFileResourcePath)) + { + _zipClient.ExtractAll(resourceStream, targetPath, false); + } + + try + { + await DownloadFonts(targetPath).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error getting ffmpeg font files", ex); + } + } + + private const string FontUrl = "https://www.dropbox.com/s/9nb76tybcsw5xrk/ARIALUNI.zip?dl=1"; + + /// <summary> + /// Extracts the fonts. + /// </summary> + /// <param name="targetPath">The target path.</param> + private async Task DownloadFonts(string targetPath) + { + var fontsDirectory = Path.Combine(targetPath, "fonts"); + + if (!Directory.Exists(fontsDirectory)) + { + Directory.CreateDirectory(fontsDirectory); + } + + const string fontFilename = "ARIALUNI.TTF"; + + var fontFile = Path.Combine(fontsDirectory, fontFilename); + + if (!File.Exists(fontFile)) + { + await DownloadFontFile(fontsDirectory, fontFilename).ConfigureAwait(false); + } + + await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false); + } + + /// <summary> + /// Downloads the font file. + /// </summary> + /// <param name="fontsDirectory">The fonts directory.</param> + /// <param name="fontFilename">The font filename.</param> + /// <returns>Task.</returns> + private async Task DownloadFontFile(string fontsDirectory, string fontFilename) + { + var existingFile = Directory + .EnumerateFiles(_appPaths.ProgramDataPath, fontFilename, SearchOption.AllDirectories) + .FirstOrDefault(); + + if (existingFile != null) + { + try + { + File.Copy(existingFile, Path.Combine(fontsDirectory, fontFilename), true); + return; + } + catch (IOException ex) + { + // Log this, but don't let it fail the operation + _logger.ErrorException("Error copying file", ex); + } + } + + var tempFile = await _httpClient.GetTempFile(new HttpRequestOptions + { + Url = FontUrl, + Progress = new Progress<double>() + }); + + _zipClient.ExtractAll(tempFile, fontsDirectory, true); + + try + { + File.Delete(tempFile); + } + catch (IOException ex) + { + // Log this, but don't let it fail the operation + _logger.ErrorException("Error deleting temp file {0}", ex, tempFile); + } + } + + /// <summary> + /// Writes the font config file. + /// </summary> + /// <param name="fontsDirectory">The fonts directory.</param> + /// <returns>Task.</returns> + private async Task WriteFontConfigFile(string fontsDirectory) + { + const string fontConfigFilename = "fonts.conf"; + var fontConfigFile = Path.Combine(fontsDirectory, fontConfigFilename); + + if (!File.Exists(fontConfigFile)) + { + var contents = string.Format("<?xml version=\"1.0\"?><fontconfig><dir>{0}</dir><alias><family>Arial</family><prefer>Arial Unicode MS</prefer></alias></fontconfig>", fontsDirectory); + + var bytes = Encoding.UTF8.GetBytes(contents); + + using (var fileStream = new FileStream(fontConfigFile, FileMode.Create, FileAccess.Write, + FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, + FileOptions.Asynchronous)) + { + await fileStream.WriteAsync(bytes, 0, bytes.Length); + } + } + } + + /// <summary> + /// Gets the media tools path. + /// </summary> + /// <param name="create">if set to <c>true</c> [create].</param> + /// <returns>System.String.</returns> + private string GetMediaToolsPath(bool create) + { + var path = Path.Combine(_appPaths.ProgramDataPath, "ffmpeg"); + + if (create && !Directory.Exists(path)) + { + Directory.CreateDirectory(path); + } + + return path; + } + } + + public class FFMpegInfo + { + public string Path { get; set; } + public string ProbePath { get; set; } + public string Version { get; set; } + } +} diff --git a/MediaBrowser.ServerApplication/Implementations/ffmpeg20130904.zip.REMOVED.git-id b/MediaBrowser.ServerApplication/Implementations/ffmpeg20130904.zip.REMOVED.git-id new file mode 100644 index 000000000..e99d115a4 --- /dev/null +++ b/MediaBrowser.ServerApplication/Implementations/ffmpeg20130904.zip.REMOVED.git-id @@ -0,0 +1 @@ +3496b2cde22e7c4cb56b480dd2da637167d51e78
\ No newline at end of file diff --git a/MediaBrowser.ServerApplication/Implementations/readme.txt b/MediaBrowser.ServerApplication/Implementations/readme.txt new file mode 100644 index 000000000..b32dd9aec --- /dev/null +++ b/MediaBrowser.ServerApplication/Implementations/readme.txt @@ -0,0 +1,5 @@ +This is the 32-bit static build of ffmpeg, located at: + +http://ffmpeg.zeranoe.com/builds/ + +The zip file contains both ffmpeg and ffprobe, and is suffixed with the date of the build.
\ No newline at end of file diff --git a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj index 3dc4faee6..043d5c18f 100644 --- a/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj +++ b/MediaBrowser.ServerApplication/MediaBrowser.ServerApplication.csproj @@ -142,17 +142,17 @@ <SpecificVersion>False</SpecificVersion> <HintPath>..\packages\MediaBrowser.IsoMounting.3.0.56\lib\net45\pfmclrapi.dll</HintPath> </Reference> - <Reference Include="ServiceStack, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL"> + <Reference Include="ServiceStack, Version=3.9.60.0, Culture=neutral, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\ServiceStack.3.9.59\lib\net35\ServiceStack.dll</HintPath> + <HintPath>..\packages\ServiceStack.3.9.62\lib\net35\ServiceStack.dll</HintPath> </Reference> - <Reference Include="ServiceStack.Common, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL"> + <Reference Include="ServiceStack.Common, Version=3.9.60.0, Culture=neutral, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\ServiceStack.Common.3.9.59\lib\net35\ServiceStack.Common.dll</HintPath> + <HintPath>..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Common.dll</HintPath> </Reference> - <Reference Include="ServiceStack.Interfaces, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL"> + <Reference Include="ServiceStack.Interfaces, Version=3.9.60.0, Culture=neutral, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\ServiceStack.Common.3.9.59\lib\net35\ServiceStack.Interfaces.dll</HintPath> + <HintPath>..\packages\ServiceStack.Common.3.9.62\lib\net35\ServiceStack.Interfaces.dll</HintPath> </Reference> <Reference Include="ServiceStack.OrmLite.SqlServer"> <HintPath>..\packages\ServiceStack.OrmLite.SqlServer.3.9.44\lib\ServiceStack.OrmLite.SqlServer.dll</HintPath> @@ -160,13 +160,13 @@ <Reference Include="ServiceStack.Redis"> <HintPath>..\packages\ServiceStack.Redis.3.9.44\lib\net35\ServiceStack.Redis.dll</HintPath> </Reference> - <Reference Include="ServiceStack.ServiceInterface, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL"> + <Reference Include="ServiceStack.ServiceInterface, Version=3.9.60.0, Culture=neutral, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\ServiceStack.3.9.59\lib\net35\ServiceStack.ServiceInterface.dll</HintPath> + <HintPath>..\packages\ServiceStack.3.9.62\lib\net35\ServiceStack.ServiceInterface.dll</HintPath> </Reference> <Reference Include="ServiceStack.Text, Version=3.9.59.0, Culture=neutral, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> - <HintPath>..\packages\ServiceStack.Text.3.9.59\lib\net35\ServiceStack.Text.dll</HintPath> + <HintPath>..\packages\ServiceStack.Text.3.9.62\lib\net35\ServiceStack.Text.dll</HintPath> </Reference> <Reference Include="SimpleInjector, Version=2.3.5.0, Culture=neutral, PublicKeyToken=984cb50dea722e99, processorArchitecture=MSIL"> <SpecificVersion>False</SpecificVersion> @@ -210,6 +210,7 @@ </Compile> <Compile Include="EntryPoints\StartupWizard.cs" /> <Compile Include="EntryPoints\UdpServerEntryPoint.cs" /> + <Compile Include="Implementations\FFMpegDownloader.cs" /> <Compile Include="MainStartup.cs" /> <Compile Include="BackgroundServiceInstaller.cs"> <SubType>Component</SubType> @@ -277,6 +278,7 @@ <LastGenOutput>Resources.Designer.cs</LastGenOutput> </EmbeddedResource> <None Include="app.manifest" /> + <EmbeddedResource Include="Implementations\ffmpeg20130904.zip" /> <None Include="packages.config" /> <None Include="Properties\Settings.settings"> <Generator>SettingsSingleFileGenerator</Generator> @@ -388,6 +390,9 @@ <ItemGroup> <Resource Include="Resources\Images\mb3logo800.png" /> </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="Implementations\readme.txt" /> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <PropertyGroup> <PostBuildEvent>if $(ConfigurationName) == Release ( diff --git a/MediaBrowser.ServerApplication/packages.config b/MediaBrowser.ServerApplication/packages.config index 24f768a9b..8c1821ca5 100644 --- a/MediaBrowser.ServerApplication/packages.config +++ b/MediaBrowser.ServerApplication/packages.config @@ -6,11 +6,11 @@ <package id="MediaBrowser.IsoMounting" version="3.0.56" targetFramework="net45" /> <package id="morelinq" version="1.0.16006" targetFramework="net45" /> <package id="NLog" version="2.0.1.2" targetFramework="net45" /> - <package id="ServiceStack" version="3.9.59" targetFramework="net45" /> - <package id="ServiceStack.Common" version="3.9.59" targetFramework="net45" /> + <package id="ServiceStack" version="3.9.62" targetFramework="net45" /> + <package id="ServiceStack.Common" version="3.9.62" targetFramework="net45" /> <package id="ServiceStack.OrmLite.SqlServer" version="3.9.44" targetFramework="net45" /> <package id="ServiceStack.Redis" version="3.9.44" targetFramework="net45" /> - <package id="ServiceStack.Text" version="3.9.59" targetFramework="net45" /> + <package id="ServiceStack.Text" version="3.9.62" targetFramework="net45" /> <package id="SimpleInjector" version="2.3.5" targetFramework="net45" /> <package id="System.Data.SQLite.x86" version="1.0.88.0" targetFramework="net45" /> </packages>
\ No newline at end of file |
