mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-04-20 17:14:42 +01:00
move classes to portable project
This commit is contained in:
@@ -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" />
|
||||
|
||||
24
Emby.Server.Implementations/FFMpeg/FFMpegInfo.cs
Normal file
24
Emby.Server.Implementations/FFMpeg/FFMpegInfo.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
20
Emby.Server.Implementations/FFMpeg/FFMpegInstallInfo.cs
Normal file
20
Emby.Server.Implementations/FFMpeg/FFMpegInstallInfo.cs
Normal 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";
|
||||
}
|
||||
}
|
||||
}
|
||||
240
Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs
Normal file
240
Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
33
Emby.Server.Implementations/StartupOptions.cs
Normal file
33
Emby.Server.Implementations/StartupOptions.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user