diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2014-05-06 22:28:19 -0400 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2014-05-06 22:28:19 -0400 |
| commit | 0d025f7fb620bf2a24ca9aa4e5994f132e02e7c0 (patch) | |
| tree | 76137f5f868ed81725d29bbdc6ac0e3b57c304d8 /MediaBrowser.ServerApplication | |
| parent | e1dd361c7bf05af49d9210ab679e85fa00870990 (diff) | |
beginning remote subtitle downloading
Diffstat (limited to 'MediaBrowser.ServerApplication')
4 files changed, 135 insertions, 94 deletions
diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs index af400f850..c79d84e5a 100644 --- a/MediaBrowser.ServerApplication/ApplicationHost.cs +++ b/MediaBrowser.ServerApplication/ApplicationHost.cs @@ -31,11 +31,11 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Sorting; +using MediaBrowser.Controller.Subtitles; using MediaBrowser.Controller.Themes; using MediaBrowser.Dlna; using MediaBrowser.Dlna.Eventing; using MediaBrowser.Dlna.Main; -using MediaBrowser.Dlna.PlayTo; using MediaBrowser.Dlna.Server; using MediaBrowser.MediaEncoding.BdInfo; using MediaBrowser.MediaEncoding.Encoder; @@ -44,6 +44,7 @@ using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.System; using MediaBrowser.Model.Updates; using MediaBrowser.Providers.Manager; +using MediaBrowser.Providers.Subtitles; using MediaBrowser.Server.Implementations; using MediaBrowser.Server.Implementations.Channels; using MediaBrowser.Server.Implementations.Collections; @@ -193,6 +194,7 @@ namespace MediaBrowser.ServerApplication private IProviderRepository ProviderRepository { get; set; } private INotificationManager NotificationManager { get; set; } + private ISubtitleManager SubtitleManager { get; set; } /// <summary> /// Initializes a new instance of the <see cref="ApplicationHost"/> class. @@ -531,6 +533,9 @@ namespace MediaBrowser.ServerApplication NotificationManager = new NotificationManager(LogManager, UserManager, ServerConfigurationManager); RegisterSingleInstance(NotificationManager); + SubtitleManager = new SubtitleManager(LogManager.GetLogger("SubtitleManager"), FileSystemManager, LibraryMonitor); + RegisterSingleInstance(SubtitleManager); + var displayPreferencesTask = Task.Run(async () => await ConfigureDisplayPreferencesRepositories().ConfigureAwait(false)); var itemsTask = Task.Run(async () => await ConfigureItemRepositories().ConfigureAwait(false)); var userdataTask = Task.Run(async () => await ConfigureUserDataRepositories().ConfigureAwait(false)); @@ -566,7 +571,7 @@ namespace MediaBrowser.ServerApplication { var info = await new FFMpegDownloader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager).GetFFMpegInfo(progress).ConfigureAwait(false); - MediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), ApplicationPaths, JsonSerializer, info.Path, info.ProbePath, info.Version, FileSystemManager); + MediaEncoder = new MediaEncoder(LogManager.GetLogger("MediaEncoder"), ApplicationPaths, JsonSerializer, info.EncoderPath, info.ProbePath, info.Version, FileSystemManager); RegisterSingleInstance(MediaEncoder); } @@ -710,6 +715,8 @@ namespace MediaBrowser.ServerApplication LiveTvManager.AddParts(GetExports<ILiveTvService>()); + SubtitleManager.AddParts(GetExports<ISubtitleProvider>()); + SessionManager.AddParts(GetExports<ISessionControllerFactory>()); ChannelManager.AddParts(GetExports<IChannel>(), GetExports<IChannelFactory>()); diff --git a/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloadInfo.cs b/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloadInfo.cs index c4f529754..19aa7a684 100644 --- a/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloadInfo.cs +++ b/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloadInfo.cs @@ -4,6 +4,8 @@ using Mono.Unix.Native; using System.Text.RegularExpressions; using System.IO; #endif +using System.IO; +using System.Text.RegularExpressions; namespace MediaBrowser.ServerApplication.FFMpeg { @@ -32,7 +34,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg switch (arg) { case "Version": - return "20140304"; + return "20140506"; case "FFMpegFilename": return "ffmpeg.exe"; case "FFProbeFilename": @@ -42,7 +44,6 @@ namespace MediaBrowser.ServerApplication.FFMpeg } break; - #if __MonoCS__ case PlatformID.Unix: if (PlatformDetection.IsMac) { @@ -69,7 +70,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg switch (arg) { case "Version": - return "20140304"; + return "20140506"; case "FFMpegFilename": return "ffmpeg"; case "FFProbeFilename": @@ -85,7 +86,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg switch (arg) { case "Version": - return "20140304"; + return "20140505"; case "FFMpegFilename": return "ffmpeg"; case "FFProbeFilename": @@ -98,7 +99,6 @@ namespace MediaBrowser.ServerApplication.FFMpeg } // Unsupported Unix platform return ""; -#endif } return ""; } @@ -106,18 +106,17 @@ namespace MediaBrowser.ServerApplication.FFMpeg private static string[] GetDownloadUrls() { var pid = Environment.OSVersion.Platform; - + switch (pid) { case PlatformID.Win32NT: return new[] { - "http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20140304-git-f34cceb-win32-static.7z", - "https://www.dropbox.com/s/6brdetuzbld93jk/ffmpeg-20140304-git-f34cceb-win32-static.7z?dl=1" + "http://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-20140506-git-2baf1c8-win32-static.7z", + "https://www.dropbox.com/s/lxlzxs0r83iatsv/ffmpeg-20140506-git-2baf1c8-win32-static.7z?dl=1" }; - - #if __MonoCS__ - case PlatformID.Unix: + + case PlatformID.Unix: if (PlatformDetection.IsMac && PlatformDetection.IsX86_64) { return new[] @@ -132,8 +131,8 @@ namespace MediaBrowser.ServerApplication.FFMpeg { return new[] { - "http://ffmpeg.gusari.org/static/32bit/ffmpeg.static.32bit.2014-03-04.tar.gz", - "https://www.dropbox.com/s/0l76mcauqqkta31/ffmpeg.static.32bit.2014-03-04.tar.gz?dl=1" + "http://ffmpeg.gusari.org/static/32bit/ffmpeg.static.32bit.latest.tar.gz", + "https://www.dropbox.com/s/k9s02pv5to6slfb/ffmpeg.static.32bit.2014-05-06.tar.gz?dl=1" }; } @@ -141,22 +140,20 @@ namespace MediaBrowser.ServerApplication.FFMpeg { return new[] { - "http://ffmpeg.gusari.org/static/64bit/ffmpeg.static.64bit.2014-03-04.tar.gz", - "https://www.dropbox.com/s/9wlxz440mdejuqe/ffmpeg.static.64bit.2014-03-04.tar.gz?dl=1" + "http://ffmpeg.gusari.org/static/64bit/ffmpeg.static.64bit.latest.tar.gz", + "https://www.dropbox.com/s/onuregwghywnzjo/ffmpeg.static.64bit.2014-05-05.tar.gz?dl=1" }; } } //No Unix version available - return new string[] {}; -#endif + return new string[] { }; } - return new string[] {}; + return new string[] { }; } } - #if __MonoCS__ public static class PlatformDetection { public readonly static bool IsWindows; @@ -166,34 +163,52 @@ namespace MediaBrowser.ServerApplication.FFMpeg public readonly static bool IsX86_64; public readonly static bool IsArm; - static PlatformDetection () + static PlatformDetection() { IsWindows = Path.DirectorySeparatorChar == '\\'; //Don't call uname on windows if (!IsWindows) { - Utsname uname; - var callResult = Syscall.uname(out uname); - if (callResult == 0) - { - IsMac = uname.sysname == "Darwin"; - IsLinux = !IsMac && uname.sysname == "Linux"; + var uname = GetUnixName(); - Regex archX86 = new Regex("(i|I)[3-6]86"); - IsX86 = archX86.IsMatch(uname.machine); - IsX86_64 = !IsX86 && uname.machine == "x86_64"; - IsArm = !IsX86 && !IsX86 && uname.machine.StartsWith("arm"); - } + IsMac = uname.sysname == "Darwin"; + IsLinux = uname.sysname == "Linux"; + + var archX86 = new Regex("(i|I)[3-6]86"); + IsX86 = archX86.IsMatch(uname.machine); + IsX86_64 = !IsX86 && uname.machine == "x86_64"; + IsArm = !IsX86 && !IsX86_64 && uname.machine.StartsWith("arm"); } else { - if (System.Environment.Is64BitOperatingSystem) + if (Environment.Is64BitOperatingSystem) IsX86_64 = true; else IsX86 = true; } } + + private static Uname GetUnixName() + { + var uname = new Uname(); + +#if __MonoCS__ + Utsname uname; + var callResult = Syscall.uname(out uname); + if (callResult == 0) + { + uname.sysname= uname.sysname; + uname.machine= uname.machine; + } +#endif + return uname; + } + } + + public class Uname + { + public string sysname = string.Empty; + public string machine = string.Empty; } - #endif } diff --git a/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs b/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs index b9c45e0d9..c550cb27f 100644 --- a/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs +++ b/MediaBrowser.ServerApplication/FFMpeg/FFMpegDownloader.cs @@ -42,63 +42,86 @@ namespace MediaBrowser.ServerApplication.FFMpeg public async Task<FFMpegInfo> GetFFMpegInfo(IProgress<double> progress) { - var versionedDirectoryPath = Path.Combine(GetMediaToolsPath(true), FFMpegDownloadInfo.Version); + var rootEncoderPath = Path.Combine(_appPaths.ProgramDataPath, "ffmpeg"); + var versionedDirectoryPath = Path.Combine(rootEncoderPath, FFMpegDownloadInfo.Version); var info = new FFMpegInfo { ProbePath = Path.Combine(versionedDirectoryPath, FFMpegDownloadInfo.FFProbeFilename), - Path = Path.Combine(versionedDirectoryPath, FFMpegDownloadInfo.FFMpegFilename), + EncoderPath = Path.Combine(versionedDirectoryPath, FFMpegDownloadInfo.FFMpegFilename), Version = FFMpegDownloadInfo.Version }; Directory.CreateDirectory(versionedDirectoryPath); - var tasks = new List<Task>(); - - double ffmpegPercent = 0; - double fontPercent = 0; - var syncLock = new object(); - - if (!File.Exists(info.ProbePath) || !File.Exists(info.Path)) + if (!File.Exists(info.ProbePath) || !File.Exists(info.EncoderPath)) { - var ffmpegProgress = new ActionableProgress<double>(); - ffmpegProgress.RegisterAction(p => - { - ffmpegPercent = p; + // ffmpeg not present. See if there's an older version we can start with + var existingVersion = GetExistingVersion(info, rootEncoderPath); - lock (syncLock) - { - progress.Report((ffmpegPercent / 2) + (fontPercent / 2)); - } - }); + // No older version. Need to download and block until complete + if (existingVersion == null) + { + await DownloadFFMpeg(versionedDirectoryPath, progress).ConfigureAwait(false); + } + else + { + // Older version found. + // Start with that. Download new version in the background. + var newPath = versionedDirectoryPath; + Task.Run(() => DownloadFFMpegInBackground(newPath)); - tasks.Add(DownloadFFMpeg(info, ffmpegProgress)); - } - else - { - ffmpegPercent = 100; - progress.Report(50); + info = existingVersion; + versionedDirectoryPath = Path.GetDirectoryName(info.EncoderPath); + } } - var fontProgress = new ActionableProgress<double>(); - fontProgress.RegisterAction(p => + await DownloadFonts(versionedDirectoryPath).ConfigureAwait(false); + + return info; + } + + private FFMpegInfo GetExistingVersion(FFMpegInfo info, string rootEncoderPath) + { + var encoderFilename = Path.GetFileName(info.EncoderPath); + var probeFilename = Path.GetFileName(info.ProbePath); + + foreach (var directory in Directory.EnumerateDirectories(rootEncoderPath, "*", SearchOption.TopDirectoryOnly) + .ToList()) { - fontPercent = p; + var allFiles = Directory.EnumerateFiles(directory, "*", SearchOption.AllDirectories).ToList(); - lock (syncLock) + var encoder = allFiles.FirstOrDefault(i => string.Equals(Path.GetFileName(i), encoderFilename, StringComparison.OrdinalIgnoreCase)); + var probe = allFiles.FirstOrDefault(i => string.Equals(Path.GetFileName(i), probeFilename, StringComparison.OrdinalIgnoreCase)); + + if (!string.IsNullOrWhiteSpace(encoder) && + !string.IsNullOrWhiteSpace(probe)) { - progress.Report((ffmpegPercent / 2) + (fontPercent / 2)); + return new FFMpegInfo + { + EncoderPath = encoder, + ProbePath = probe, + Version = Path.GetFileNameWithoutExtension(Path.GetDirectoryName(probe)) + }; } - }); - - tasks.Add(DownloadFonts(versionedDirectoryPath, fontProgress)); + } - await Task.WhenAll(tasks).ConfigureAwait(false); + return null; + } - return info; + private async void DownloadFFMpegInBackground(string directory) + { + try + { + await DownloadFFMpeg(directory, new Progress<double>()).ConfigureAwait(false); + } + catch (Exception ex) + { + _logger.ErrorException("Error downloading ffmpeg", ex); + } } - private async Task DownloadFFMpeg(FFMpegInfo info, IProgress<double> progress) + private async Task DownloadFFMpeg(string directory, IProgress<double> progress) { foreach (var url in FFMpegDownloadInfo.FfMpegUrls) { @@ -114,7 +137,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg }).ConfigureAwait(false); - ExtractFFMpeg(tempFile, Path.GetDirectoryName(info.Path)); + ExtractFFMpeg(tempFile, directory); return; } catch (HttpException ex) @@ -132,7 +155,7 @@ namespace MediaBrowser.ServerApplication.FFMpeg private void ExtractFFMpeg(string tempFile, string targetFolder) { - _logger.Debug("Extracting ffmpeg from {0}", tempFile); + _logger.Info("Extracting ffmpeg from {0}", tempFile); var tempFolder = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString()); @@ -171,6 +194,8 @@ namespace MediaBrowser.ServerApplication.FFMpeg private void ExtractArchive(string archivePath, string targetPath) { + _logger.Info("Extracting {0} to {1}", archivePath, targetPath); + if (string.Equals(FFMpegDownloadInfo.ArchiveType, "7z", StringComparison.OrdinalIgnoreCase)) { _zipClient.ExtractAllFrom7z(archivePath, targetPath, true); @@ -182,6 +207,8 @@ namespace MediaBrowser.ServerApplication.FFMpeg } private void Extract7zArchive(string archivePath, string targetPath) { + _logger.Info("Extracting {0} to {1}", archivePath, targetPath); + _zipClient.ExtractAllFrom7z(archivePath, targetPath, true); } @@ -201,7 +228,8 @@ namespace MediaBrowser.ServerApplication.FFMpeg /// Extracts the fonts. /// </summary> /// <param name="targetPath">The target path.</param> - private async Task DownloadFonts(string targetPath, IProgress<double> progress) + /// <returns>Task.</returns> + private async Task DownloadFonts(string targetPath) { try { @@ -213,12 +241,19 @@ namespace MediaBrowser.ServerApplication.FFMpeg var fontFile = Path.Combine(fontsDirectory, fontFilename); - if (!File.Exists(fontFile)) + if (File.Exists(fontFile)) { - await DownloadFontFile(fontsDirectory, fontFilename, progress).ConfigureAwait(false); + await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false); + } + else + { + // Kick this off, but no need to wait on it + Task.Run(async () => + { + await DownloadFontFile(fontsDirectory, fontFilename, new Progress<double>()).ConfigureAwait(false); + await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false); + }); } - - await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false); } catch (HttpException ex) { @@ -230,8 +265,6 @@ namespace MediaBrowser.ServerApplication.FFMpeg // Don't let the server crash because of this _logger.ErrorException("Error writing ffmpeg font files", ex); } - - progress.Report(100); } /// <summary> @@ -325,19 +358,5 @@ namespace MediaBrowser.ServerApplication.FFMpeg } } } - - /// <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"); - - Directory.CreateDirectory(path); - - return path; - } } } diff --git a/MediaBrowser.ServerApplication/FFMpeg/FFMpegInfo.cs b/MediaBrowser.ServerApplication/FFMpeg/FFMpegInfo.cs index 147a9f771..1361277aa 100644 --- a/MediaBrowser.ServerApplication/FFMpeg/FFMpegInfo.cs +++ b/MediaBrowser.ServerApplication/FFMpeg/FFMpegInfo.cs @@ -9,7 +9,7 @@ /// Gets or sets the path. /// </summary> /// <value>The path.</value> - public string Path { get; set; } + public string EncoderPath { get; set; } /// <summary> /// Gets or sets the probe path. /// </summary> |
