move classes to portable project

This commit is contained in:
Luke Pulverenti
2016-11-18 16:06:00 -05:00
parent c6f1bd93fc
commit e58e34ceca
11 changed files with 31 additions and 17 deletions

View File

@@ -69,6 +69,9 @@
<Compile Include="EntryPoints\UsageEntryPoint.cs" />
<Compile Include="EntryPoints\UsageReporter.cs" />
<Compile Include="EntryPoints\UserDataChangeNotifier.cs" />
<Compile Include="FFMpeg\FFMpegInfo.cs" />
<Compile Include="FFMpeg\FFMpegInstallInfo.cs" />
<Compile Include="FFMpeg\FFMpegLoader.cs" />
<Compile Include="FileOrganization\EpisodeFileOrganizer.cs" />
<Compile Include="FileOrganization\Extensions.cs" />
<Compile Include="FileOrganization\FileOrganizationNotifier.cs" />
@@ -239,6 +242,7 @@
<Compile Include="Sorting\SortNameComparer.cs" />
<Compile Include="Sorting\StartDateComparer.cs" />
<Compile Include="Sorting\StudioComparer.cs" />
<Compile Include="StartupOptions.cs" />
<Compile Include="Sync\AppSyncProvider.cs" />
<Compile Include="Sync\CloudSyncProfile.cs" />
<Compile Include="Sync\IHasSyncQuality.cs" />

View File

@@ -0,0 +1,24 @@
namespace Emby.Server.Implementations.FFMpeg
{
/// <summary>
/// Class FFMpegInfo
/// </summary>
public class FFMpegInfo
{
/// <summary>
/// Gets or sets the path.
/// </summary>
/// <value>The path.</value>
public string EncoderPath { get; set; }
/// <summary>
/// Gets or sets the probe path.
/// </summary>
/// <value>The probe path.</value>
public string ProbePath { get; set; }
/// <summary>
/// Gets or sets the version.
/// </summary>
/// <value>The version.</value>
public string Version { get; set; }
}
}

View File

@@ -0,0 +1,20 @@

namespace Emby.Server.Implementations.FFMpeg
{
public class FFMpegInstallInfo
{
public string Version { get; set; }
public string FFMpegFilename { get; set; }
public string FFProbeFilename { get; set; }
public string ArchiveType { get; set; }
public string[] DownloadUrls { get; set; }
public FFMpegInstallInfo()
{
DownloadUrls = new string[] { };
Version = "Path";
FFMpegFilename = "ffmpeg";
FFProbeFilename = "ffprobe";
}
}
}

View File

@@ -0,0 +1,240 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Net;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Emby.Server.Implementations;
using Emby.Server.Implementations.FFMpeg;
namespace Emby.Server.Implementations.FFMpeg
{
public class FFMpegLoader
{
private readonly IHttpClient _httpClient;
private readonly IApplicationPaths _appPaths;
private readonly ILogger _logger;
private readonly IZipClient _zipClient;
private readonly IFileSystem _fileSystem;
private readonly FFMpegInstallInfo _ffmpegInstallInfo;
public FFMpegLoader(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IZipClient zipClient, IFileSystem fileSystem, FFMpegInstallInfo ffmpegInstallInfo)
{
_logger = logger;
_appPaths = appPaths;
_httpClient = httpClient;
_zipClient = zipClient;
_fileSystem = fileSystem;
_ffmpegInstallInfo = ffmpegInstallInfo;
}
public async Task<FFMpegInfo> GetFFMpegInfo(StartupOptions options, IProgress<double> progress)
{
var customffMpegPath = options.GetOption("-ffmpeg");
var customffProbePath = options.GetOption("-ffprobe");
if (!string.IsNullOrWhiteSpace(customffMpegPath) && !string.IsNullOrWhiteSpace(customffProbePath))
{
return new FFMpegInfo
{
ProbePath = customffProbePath,
EncoderPath = customffMpegPath,
Version = "external"
};
}
var downloadInfo = _ffmpegInstallInfo;
var version = downloadInfo.Version;
if (string.Equals(version, "path", StringComparison.OrdinalIgnoreCase))
{
return new FFMpegInfo
{
ProbePath = downloadInfo.FFProbeFilename,
EncoderPath = downloadInfo.FFMpegFilename,
Version = version
};
}
if (string.Equals(version, "0", StringComparison.OrdinalIgnoreCase))
{
return new FFMpegInfo();
}
var rootEncoderPath = Path.Combine(_appPaths.ProgramDataPath, "ffmpeg");
var versionedDirectoryPath = Path.Combine(rootEncoderPath, version);
var info = new FFMpegInfo
{
ProbePath = Path.Combine(versionedDirectoryPath, downloadInfo.FFProbeFilename),
EncoderPath = Path.Combine(versionedDirectoryPath, downloadInfo.FFMpegFilename),
Version = version
};
_fileSystem.CreateDirectory(versionedDirectoryPath);
var excludeFromDeletions = new List<string> { versionedDirectoryPath };
if (!_fileSystem.FileExists(info.ProbePath) || !_fileSystem.FileExists(info.EncoderPath))
{
// ffmpeg not present. See if there's an older version we can start with
var existingVersion = GetExistingVersion(info, rootEncoderPath);
// No older version. Need to download and block until complete
if (existingVersion == null)
{
var success = await DownloadFFMpeg(downloadInfo, versionedDirectoryPath, progress).ConfigureAwait(false);
if (!success)
{
return new FFMpegInfo();
}
}
else
{
info = existingVersion;
versionedDirectoryPath = Path.GetDirectoryName(info.EncoderPath);
excludeFromDeletions.Add(versionedDirectoryPath);
}
}
// Allow just one of these to be overridden, if desired.
if (!string.IsNullOrWhiteSpace(customffMpegPath))
{
info.EncoderPath = customffMpegPath;
}
if (!string.IsNullOrWhiteSpace(customffProbePath))
{
info.EncoderPath = customffProbePath;
}
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 _fileSystem.GetDirectoryPaths(rootEncoderPath)
.ToList())
{
var allFiles = _fileSystem.GetFilePaths(directory, true).ToList();
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))
{
return new FFMpegInfo
{
EncoderPath = encoder,
ProbePath = probe,
Version = Path.GetFileName(Path.GetDirectoryName(probe))
};
}
}
return null;
}
private async Task<bool> DownloadFFMpeg(FFMpegInstallInfo downloadinfo, string directory, IProgress<double> progress)
{
foreach (var url in downloadinfo.DownloadUrls)
{
progress.Report(0);
try
{
var tempFile = await _httpClient.GetTempFile(new HttpRequestOptions
{
Url = url,
CancellationToken = CancellationToken.None,
Progress = progress
}).ConfigureAwait(false);
ExtractFFMpeg(downloadinfo, tempFile, directory);
return true;
}
catch (Exception ex)
{
_logger.ErrorException("Error downloading {0}", ex, url);
}
}
return false;
}
private void ExtractFFMpeg(FFMpegInstallInfo downloadinfo, string tempFile, string targetFolder)
{
_logger.Info("Extracting ffmpeg from {0}", tempFile);
var tempFolder = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid().ToString());
_fileSystem.CreateDirectory(tempFolder);
try
{
ExtractArchive(downloadinfo, tempFile, tempFolder);
var files = _fileSystem.GetFilePaths(tempFolder, true)
.ToList();
foreach (var file in files.Where(i =>
{
var filename = Path.GetFileName(i);
return
string.Equals(filename, downloadinfo.FFProbeFilename, StringComparison.OrdinalIgnoreCase) ||
string.Equals(filename, downloadinfo.FFMpegFilename, StringComparison.OrdinalIgnoreCase);
}))
{
var targetFile = Path.Combine(targetFolder, Path.GetFileName(file));
_fileSystem.CopyFile(file, targetFile, true);
SetFilePermissions(targetFile);
}
}
finally
{
DeleteFile(tempFile);
}
}
private void SetFilePermissions(string path)
{
_fileSystem.SetExecutable(path);
}
private void ExtractArchive(FFMpegInstallInfo downloadinfo, string archivePath, string targetPath)
{
_logger.Info("Extracting {0} to {1}", archivePath, targetPath);
if (string.Equals(downloadinfo.ArchiveType, "7z", StringComparison.OrdinalIgnoreCase))
{
_zipClient.ExtractAllFrom7z(archivePath, targetPath, true);
}
else if (string.Equals(downloadinfo.ArchiveType, "gz", StringComparison.OrdinalIgnoreCase))
{
_zipClient.ExtractAllFromTar(archivePath, targetPath, true);
}
}
private void DeleteFile(string path)
{
try
{
_fileSystem.DeleteFile(path);
}
catch (IOException ex)
{
_logger.ErrorException("Error deleting temp file {0}", ex, path);
}
}
}
}

View File

@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
namespace Emby.Server.Implementations
{
public class StartupOptions
{
private readonly List<string> _options;
public StartupOptions(string[] commandLineArgs)
{
_options = commandLineArgs.ToList();
}
public bool ContainsOption(string option)
{
return _options.Contains(option, StringComparer.OrdinalIgnoreCase);
}
public string GetOption(string name)
{
var index = _options.IndexOf(name);
if (index != -1)
{
return _options.ElementAtOrDefault(index + 1);
}
return null;
}
}
}