diff options
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | CONTRIBUTORS.md | 13 | ||||
| -rw-r--r-- | Emby.Server.Implementations/ApplicationHost.cs | 55 | ||||
| -rw-r--r-- | Emby.Server.Implementations/Channels/ChannelManager.cs | 4 | ||||
| -rw-r--r-- | Emby.Server.Implementations/IO/SharpCifs/Smb/SmbFile.cs | 20 | ||||
| -rw-r--r-- | Emby.Server.Implementations/Networking/IPNetwork/IPNetwork.cs | 106 | ||||
| -rw-r--r-- | Emby.Server.Implementations/ScheduledTasks/PluginUpdateTask.cs | 142 | ||||
| -rw-r--r-- | Emby.Server.Implementations/ScheduledTasks/SystemUpdateTask.cs | 128 | ||||
| -rw-r--r-- | Jellyfin.Server/CoreAppHost.cs | 4 | ||||
| -rw-r--r-- | Jellyfin.Server/Program.cs | 1 | ||||
| -rw-r--r-- | MediaBrowser.Common/Extensions/BaseExtensions.cs | 20 | ||||
| -rw-r--r-- | MediaBrowser.Common/IApplicationHost.cs | 6 | ||||
| -rw-r--r-- | MediaBrowser.Common/Updates/GithubUpdater.cs | 274 | ||||
| -rw-r--r-- | MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs | 104 | ||||
| -rw-r--r-- | MediaBrowser.MediaEncoding/Encoder/FontConfigLoader.cs | 179 | ||||
| -rw-r--r-- | MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs | 41 |
16 files changed, 78 insertions, 1021 deletions
diff --git a/.gitignore b/.gitignore index ff9e52259..9bbfd9b74 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ !* +.directory + ################# ## Eclipse ################# diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 3a2c229d1..e6892313c 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -8,15 +8,16 @@ - [flemse](https://github.com/flemse) - [bfayers](https://github.com/bfayers) - [Bond_009](https://github.com/Bond-009) + - [sparky8251](https://github.com/sparky8251) # Emby Contributors - - [LukePulverenti](https://github.com/LukePulverenti) - - [ebr11](https://github.com/ebr11) - - [lalmanzar](https://github.com/lalmanzar) - - [schneifu](https://github.com/schneifu) - - [Mark2xv](https://github.com/Mark2xv) - - [ScottRapsey](https://github.com/ScottRapsey) + - [LukePulverenti](https://github.com/LukePulverenti) + - [ebr11](https://github.com/ebr11) + - [lalmanzar](https://github.com/lalmanzar) + - [schneifu](https://github.com/schneifu) + - [Mark2xv](https://github.com/Mark2xv) + - [ScottRapsey](https://github.com/ScottRapsey) - [skynet600](https://github.com/skynet600) - [Cheesegeezer](https://githum.com/Cheesegeezer) - [Radeon](https://github.com/radeonorama) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index f1e1b4b2d..3cc6151f1 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -368,7 +368,6 @@ namespace Emby.Server.Implementations protected IAuthService AuthService { get; private set; } public StartupOptions StartupOptions { get; private set; } - protected readonly string ReleaseAssetFilename; internal IPowerManagement PowerManagement { get; private set; } internal IImageEncoder ImageEncoder { get; private set; } @@ -393,7 +392,6 @@ namespace Emby.Server.Implementations StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, - string releaseAssetFilename, IEnvironmentInfo environmentInfo, IImageEncoder imageEncoder, ISystemEvents systemEvents, @@ -419,7 +417,6 @@ namespace Emby.Server.Implementations Logger = LoggerFactory.CreateLogger("App"); StartupOptions = options; - ReleaseAssetFilename = releaseAssetFilename; PowerManagement = powerManagement; ImageEncoder = imageEncoder; @@ -1240,7 +1237,7 @@ namespace Emby.Server.Implementations HttpClient, ZipClient, ProcessFactory, - 5000, false, + 5000, EnvironmentInfo); MediaEncoder = mediaEncoder; @@ -2287,56 +2284,6 @@ namespace Emby.Server.Implementations } /// <summary> - /// Checks for update. - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task{CheckForUpdateResult}.</returns> - public async Task<CheckForUpdateResult> CheckForApplicationUpdate(CancellationToken cancellationToken, IProgress<double> progress) - { - var updateLevel = SystemUpdateLevel; - var cacheLength = updateLevel == PackageVersionClass.Release ? - TimeSpan.FromHours(12) : - TimeSpan.FromMinutes(5); - - try - { - var result = await new GithubUpdater(HttpClient, JsonSerializer).CheckForUpdateResult("MediaBrowser", - "Emby.Releases", - ApplicationVersion, - updateLevel, - ReleaseAssetFilename, - "MBServer", - UpdateTargetFileName, - cacheLength, - cancellationToken).ConfigureAwait(false); - - HasUpdateAvailable = result.IsUpdateAvailable; - - return result; - } - catch (HttpException ex) - { - // users are overreacting to this occasionally failing - if (ex.StatusCode.HasValue && ex.StatusCode.Value == HttpStatusCode.Forbidden) - { - HasUpdateAvailable = false; - return new CheckForUpdateResult - { - IsUpdateAvailable = false - }; - } - - throw; - } - } - - protected virtual string UpdateTargetFileName - { - get { return "Mbserver.zip"; } - } - - /// <summary> /// Updates the application. /// </summary> /// <param name="package">The package that contains the update</param> diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs index 00da46f30..c2160d338 100644 --- a/Emby.Server.Implementations/Channels/ChannelManager.cs +++ b/Emby.Server.Implementations/Channels/ChannelManager.cs @@ -901,8 +901,8 @@ namespace Emby.Server.Implementations.Channels private T GetItemById<T>(string idString, string channelName, out bool isNew) where T : BaseItem, new() { - var id = GetIdToHash(idString, channelName).GetMBId(typeof(T)); - + var id = _libraryManager.GetNewItemId(GetIdToHash(idString, channelName), typeof(T)); + T item = null; try diff --git a/Emby.Server.Implementations/IO/SharpCifs/Smb/SmbFile.cs b/Emby.Server.Implementations/IO/SharpCifs/Smb/SmbFile.cs index 151ec35c4..7fd9f0d84 100644 --- a/Emby.Server.Implementations/IO/SharpCifs/Smb/SmbFile.cs +++ b/Emby.Server.Implementations/IO/SharpCifs/Smb/SmbFile.cs @@ -3381,26 +3381,6 @@ namespace SharpCifs.Smb } /// <summary> - /// Returns a - /// <see cref="System.Uri">System.Uri</see> - /// for this <code>SmbFile</code>. The - /// <code>URL</code> may be used as any other <code>URL</code> might to - /// access an SMB resource. Currently only retrieving data and information - /// is supported (i.e. no <tt>doOutput</tt>). - /// </summary> - /// <returns> - /// A new <code> - /// <see cref="System.Uri">System.Uri</see> - /// </code> for this <code>SmbFile</code> - /// </returns> - /// <exception cref="System.UriFormatException">System.UriFormatException</exception> - [Obsolete(@"Use getURL() instead")] - public virtual Uri ToUrl() - { - return Url; - } - - /// <summary> /// Computes a hashCode for this file based on the URL string and IP /// address if the server. /// </summary> diff --git a/Emby.Server.Implementations/Networking/IPNetwork/IPNetwork.cs b/Emby.Server.Implementations/Networking/IPNetwork/IPNetwork.cs index 6d7785b90..8d0fb7997 100644 --- a/Emby.Server.Implementations/Networking/IPNetwork/IPNetwork.cs +++ b/Emby.Server.Implementations/Networking/IPNetwork/IPNetwork.cs @@ -189,7 +189,7 @@ namespace System.Net internal #endif - IPNetwork(BigInteger ipaddress, AddressFamily family, byte cidr) + IPNetwork(BigInteger ipaddress, AddressFamily family, byte cidr) { int maxCidr = family == Sockets.AddressFamily.InterNetwork ? 32 : 128; @@ -1164,18 +1164,6 @@ namespace System.Net } - [Obsolete("static Contains is deprecated, please use instance Contains.")] - public static bool Contains(IPNetwork network, IPAddress ipaddress) - { - - if (network == null) - { - throw new ArgumentNullException("network"); - } - - return network.Contains(ipaddress); - } - /// <summary> /// return true is network2 is fully contained in network /// </summary> @@ -1201,18 +1189,6 @@ namespace System.Net return contains; } - [Obsolete("static Contains is deprecated, please use instance Contains.")] - public static bool Contains(IPNetwork network, IPNetwork network2) - { - - if (network == null) - { - throw new ArgumentNullException("network"); - } - - return network.Contains(network2); - } - #endregion #region overlap @@ -1245,18 +1221,6 @@ namespace System.Net return overlap; } - [Obsolete("static Overlap is deprecated, please use instance Overlap.")] - public static bool Overlap(IPNetwork network, IPNetwork network2) - { - - if (network == null) - { - throw new ArgumentNullException("network"); - } - - return network.Overlap(network2); - } - #endregion #region ToString @@ -1341,18 +1305,6 @@ namespace System.Net || IPNetwork.IANA_CBLK_RESERVED1.Contains(this); } - [Obsolete("static IsIANAReserved is deprecated, please use instance IsIANAReserved.")] - public static bool IsIANAReserved(IPNetwork ipnetwork) - { - - if (ipnetwork == null) - { - throw new ArgumentNullException("ipnetwork"); - } - - return ipnetwork.IsIANAReserved(); - } - #endregion #region Subnet @@ -1371,16 +1323,6 @@ namespace System.Net return ipnetworkCollection; } - [Obsolete("static Subnet is deprecated, please use instance Subnet.")] - public static IPNetworkCollection Subnet(IPNetwork network, byte cidr) - { - if (network == null) - { - throw new ArgumentNullException("network"); - } - return network.Subnet(cidr); - } - /// <summary> /// Subnet a network into multiple nets of cidr mask /// Subnet 192.168.0.0/24 into cidr 25 gives 192.168.0.0/25, 192.168.0.128/25 @@ -1402,16 +1344,6 @@ namespace System.Net return true; } - [Obsolete("static TrySubnet is deprecated, please use instance TrySubnet.")] - public static bool TrySubnet(IPNetwork network, byte cidr, out IPNetworkCollection ipnetworkCollection) - { - if (network == null) - { - throw new ArgumentNullException("network"); - } - return network.TrySubnet(cidr, out ipnetworkCollection); - } - #if TRAVISCI public #else @@ -1476,12 +1408,6 @@ namespace System.Net return supernet; } - [Obsolete("static Supernet is deprecated, please use instance Supernet.")] - public static IPNetwork Supernet(IPNetwork network, IPNetwork network2) - { - return network.Supernet(network2); - } - /// <summary> /// Try to supernet two consecutive cidr equal subnet into a single one /// 192.168.0.0/24 + 192.168.1.0/24 = 192.168.0.0/23 @@ -1500,16 +1426,6 @@ namespace System.Net return parsed; } - [Obsolete("static TrySupernet is deprecated, please use instance TrySupernet.")] - public static bool TrySupernet(IPNetwork network, IPNetwork network2, out IPNetwork supernet) - { - if (network == null) - { - throw new ArgumentNullException("network"); - } - return network.TrySupernet(network2, out supernet); - } - #if TRAVISCI public #else @@ -1920,18 +1836,6 @@ namespace System.Net return sw.ToString(); } - [Obsolete("static Print is deprecated, please use instance Print.")] - public static string Print(IPNetwork ipnetwork) - { - - if (ipnetwork == null) - { - throw new ArgumentNullException("ipnetwork"); - } - - return ipnetwork.Print(); - } - #endregion #region TryGuessCidr @@ -2018,12 +1922,6 @@ namespace System.Net #region ListIPAddress - [Obsolete("static ListIPAddress is deprecated, please use instance ListIPAddress.")] - public static IPAddressCollection ListIPAddress(IPNetwork ipnetwork) - { - return ipnetwork.ListIPAddress(); - } - public IPAddressCollection ListIPAddress() { return new IPAddressCollection(this); @@ -2167,4 +2065,4 @@ namespace System.Net #endregion } -}
\ No newline at end of file +} diff --git a/Emby.Server.Implementations/ScheduledTasks/PluginUpdateTask.cs b/Emby.Server.Implementations/ScheduledTasks/PluginUpdateTask.cs deleted file mode 100644 index 46a7f1f27..000000000 --- a/Emby.Server.Implementations/ScheduledTasks/PluginUpdateTask.cs +++ /dev/null @@ -1,142 +0,0 @@ -using MediaBrowser.Common; -using MediaBrowser.Common.Updates; -using Microsoft.Extensions.Logging; -using MediaBrowser.Model.Net; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.Progress; -using MediaBrowser.Model.Tasks; - -namespace Emby.Server.Implementations.ScheduledTasks -{ - /// <summary> - /// Plugin Update Task - /// </summary> - public class PluginUpdateTask : IScheduledTask, IConfigurableScheduledTask - { - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - - private readonly IInstallationManager _installationManager; - - private readonly IApplicationHost _appHost; - - public PluginUpdateTask(ILogger logger, IInstallationManager installationManager, IApplicationHost appHost) - { - _logger = logger; - _installationManager = installationManager; - _appHost = appHost; - } - - /// <summary> - /// Creates the triggers that define when the task will run - /// </summary> - /// <returns>IEnumerable{BaseTaskTrigger}.</returns> - public IEnumerable<TaskTriggerInfo> GetDefaultTriggers() - { - return new[] { - - // At startup - new TaskTriggerInfo {Type = TaskTriggerInfo.TriggerStartup}, - - // Every so often - new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks} - }; - } - - public string Key - { - get { return "PluginUpdates"; } - } - - /// <summary> - /// Update installed plugins - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task.</returns> - public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress) - { - progress.Report(0); - - var packagesToInstall = (await _installationManager.GetAvailablePluginUpdates(_appHost.ApplicationVersion, true, cancellationToken).ConfigureAwait(false)).ToList(); - - progress.Report(10); - - var numComplete = 0; - - foreach (var package in packagesToInstall) - { - cancellationToken.ThrowIfCancellationRequested(); - - try - { - await _installationManager.InstallPackage(package, true, new SimpleProgress<double>(), cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - // InstallPackage has it's own inner cancellation token, so only throw this if it's ours - if (cancellationToken.IsCancellationRequested) - { - throw; - } - } - catch (HttpException ex) - { - _logger.LogError(ex, "Error downloading {name}", package.name); - } - catch (IOException ex) - { - _logger.LogError(ex, "Error updating {name}", package.name); - } - - // Update progress - lock (progress) - { - numComplete++; - double percent = numComplete; - percent /= packagesToInstall.Count; - - progress.Report(90 * percent + 10); - } - } - - progress.Report(100); - } - - /// <summary> - /// Gets the name of the task - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return "Check for plugin updates"; } - } - - /// <summary> - /// Gets the description. - /// </summary> - /// <value>The description.</value> - public string Description - { - get { return "Downloads and installs updates for plugins that are configured to update automatically."; } - } - - public string Category - { - get { return "Application"; } - } - - public bool IsHidden => true; - - public bool IsEnabled => true; - - public bool IsLogged => true; - } -} diff --git a/Emby.Server.Implementations/ScheduledTasks/SystemUpdateTask.cs b/Emby.Server.Implementations/ScheduledTasks/SystemUpdateTask.cs deleted file mode 100644 index 4cb97cbda..000000000 --- a/Emby.Server.Implementations/ScheduledTasks/SystemUpdateTask.cs +++ /dev/null @@ -1,128 +0,0 @@ -using MediaBrowser.Common; -using MediaBrowser.Common.Configuration; -using Microsoft.Extensions.Logging; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.Progress; -using MediaBrowser.Model.Tasks; - -namespace Emby.Server.Implementations.ScheduledTasks -{ - /// <summary> - /// Plugin Update Task - /// </summary> - public class SystemUpdateTask : IScheduledTask - { - /// <summary> - /// The _app host - /// </summary> - private readonly IApplicationHost _appHost; - - /// <summary> - /// Gets or sets the configuration manager. - /// </summary> - /// <value>The configuration manager.</value> - private IConfigurationManager ConfigurationManager { get; set; } - /// <summary> - /// Gets or sets the logger. - /// </summary> - /// <value>The logger.</value> - private ILogger Logger { get; set; } - - /// <summary> - /// Initializes a new instance of the <see cref="SystemUpdateTask" /> class. - /// </summary> - /// <param name="appHost">The app host.</param> - /// <param name="configurationManager">The configuration manager.</param> - /// <param name="logger">The logger.</param> - public SystemUpdateTask(IApplicationHost appHost, IConfigurationManager configurationManager, ILogger logger) - { - _appHost = appHost; - ConfigurationManager = configurationManager; - Logger = logger; - } - - /// <summary> - /// Creates the triggers that define when the task will run - /// </summary> - /// <returns>IEnumerable{BaseTaskTrigger}.</returns> - public IEnumerable<TaskTriggerInfo> GetDefaultTriggers() - { - return new[] { - - // At startup - new TaskTriggerInfo {Type = TaskTriggerInfo.TriggerStartup}, - - // Every so often - new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks} - }; - } - - /// <summary> - /// Returns the task to be executed - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task.</returns> - public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress) - { - // Create a progress object for the update check - var updateInfo = await _appHost.CheckForApplicationUpdate(cancellationToken, new SimpleProgress<double>()).ConfigureAwait(false); - - if (!updateInfo.IsUpdateAvailable) - { - Logger.LogDebug("No application update available."); - return; - } - - cancellationToken.ThrowIfCancellationRequested(); - - if (!_appHost.CanSelfUpdate) return; - - if (ConfigurationManager.CommonConfiguration.EnableAutoUpdate) - { - Logger.LogInformation("Update Revision {0} available. Updating...", updateInfo.AvailableVersion); - - await _appHost.UpdateApplication(updateInfo.Package, cancellationToken, progress).ConfigureAwait(false); - } - else - { - Logger.LogInformation("A new version of " + _appHost.Name + " is available."); - } - } - - /// <summary> - /// Gets the name of the task - /// </summary> - /// <value>The name.</value> - public string Name - { - get { return "Check for application updates"; } - } - - /// <summary> - /// Gets the description. - /// </summary> - /// <value>The description.</value> - public string Description - { - get { return "Downloads and installs application updates."; } - } - - /// <summary> - /// Gets the category. - /// </summary> - /// <value>The category.</value> - public string Category - { - get { return "Application"; } - } - - public string Key - { - get { return "SystemUpdateTask"; } - } - } -} diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index 2fb106b3c..b54634387 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -11,8 +11,8 @@ namespace Jellyfin.Server { public class CoreAppHost : ApplicationHost { - public CoreAppHost(ServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, string releaseAssetFilename, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, MediaBrowser.Common.Net.INetworkManager networkManager) - : base(applicationPaths, loggerFactory, options, fileSystem, powerManagement, releaseAssetFilename, environmentInfo, imageEncoder, systemEvents, networkManager) + public CoreAppHost(ServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, StartupOptions options, IFileSystem fileSystem, IPowerManagement powerManagement, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, ISystemEvents systemEvents, MediaBrowser.Common.Net.INetworkManager networkManager) + : base(applicationPaths, loggerFactory, options, fileSystem, powerManagement, environmentInfo, imageEncoder, systemEvents, networkManager) { } diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 0150cd533..9cc2fe103 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -73,7 +73,6 @@ namespace Jellyfin.Server options,
fileSystem,
new PowerManagement(),
- "embyserver-mono_{version}.zip",
environmentInfo,
new NullImageEncoder(),
new SystemEvents(_loggerFactory.CreateLogger("SystemEvents")),
diff --git a/MediaBrowser.Common/Extensions/BaseExtensions.cs b/MediaBrowser.Common/Extensions/BaseExtensions.cs index d7f4424fa..520c04244 100644 --- a/MediaBrowser.Common/Extensions/BaseExtensions.cs +++ b/MediaBrowser.Common/Extensions/BaseExtensions.cs @@ -34,25 +34,5 @@ namespace MediaBrowser.Common.Extensions { return CryptographyProvider.GetMD5(str); } - - /// <summary> - /// Gets the MB id. - /// </summary> - /// <param name="str">The STR.</param> - /// <param name="type">The type.</param> - /// <returns>Guid.</returns> - /// <exception cref="System.ArgumentNullException">type</exception> - [Obsolete("Use LibraryManager.GetNewItemId")] - public static Guid GetMBId(this string str, Type type) - { - if (type == null) - { - throw new ArgumentNullException("type"); - } - - var key = type.FullName + str.ToLower(); - - return key.GetMD5(); - } } } diff --git a/MediaBrowser.Common/IApplicationHost.cs b/MediaBrowser.Common/IApplicationHost.cs index 32b942b60..39d69ea15 100644 --- a/MediaBrowser.Common/IApplicationHost.cs +++ b/MediaBrowser.Common/IApplicationHost.cs @@ -86,12 +86,6 @@ namespace MediaBrowser.Common IEnumerable<T> GetExports<T>(bool manageLiftime = true); /// <summary> - /// Checks for update. - /// </summary> - /// <returns>Task{CheckForUpdateResult}.</returns> - Task<CheckForUpdateResult> CheckForApplicationUpdate(CancellationToken cancellationToken, IProgress<double> progress); - - /// <summary> /// Updates the application. /// </summary> /// <returns>Task.</returns> diff --git a/MediaBrowser.Common/Updates/GithubUpdater.cs b/MediaBrowser.Common/Updates/GithubUpdater.cs deleted file mode 100644 index 22ed788e0..000000000 --- a/MediaBrowser.Common/Updates/GithubUpdater.cs +++ /dev/null @@ -1,274 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Common.Net; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.Updates; - -namespace MediaBrowser.Common.Updates -{ - public class GithubUpdater - { - private readonly IHttpClient _httpClient; - private readonly IJsonSerializer _jsonSerializer; - - public GithubUpdater(IHttpClient httpClient, IJsonSerializer jsonSerializer) - { - _httpClient = httpClient; - _jsonSerializer = jsonSerializer; - } - - public async Task<CheckForUpdateResult> CheckForUpdateResult(string organzation, string repository, Version minVersion, PackageVersionClass updateLevel, string assetFilename, string packageName, string targetFilename, TimeSpan cacheLength, CancellationToken cancellationToken) - { - var url = string.Format("https://api.github.com/repos/{0}/{1}/releases", organzation, repository); - - var options = new HttpRequestOptions - { - Url = url, - EnableKeepAlive = false, - CancellationToken = cancellationToken, - UserAgent = "Emby/3.0", - BufferContent = false - }; - - if (cacheLength.Ticks > 0) - { - options.CacheMode = CacheMode.Unconditional; - options.CacheLength = cacheLength; - } - - using (var response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false)) - using (var stream = response.Content) - { - var obj = await _jsonSerializer.DeserializeFromStreamAsync<RootObject[]>(stream).ConfigureAwait(false); - - return CheckForUpdateResult(obj, minVersion, updateLevel, assetFilename, packageName, targetFilename); - } - } - - private CheckForUpdateResult CheckForUpdateResult(RootObject[] obj, Version minVersion, PackageVersionClass updateLevel, string assetFilename, string packageName, string targetFilename) - { - if (updateLevel == PackageVersionClass.Release) - { - // Technically all we need to do is check that it's not pre-release - // But let's addititional checks for -beta and -dev to handle builds that might be temporarily tagged incorrectly. - obj = obj.Where(i => !i.prerelease && !i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase) && !i.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase)).ToArray(); - } - else if (updateLevel == PackageVersionClass.Beta) - { - obj = obj.Where(i => i.prerelease && i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase)).ToArray(); - } - else if (updateLevel == PackageVersionClass.Dev) - { - obj = obj.Where(i => !i.prerelease || i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase) || i.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase)).ToArray(); - } - - var availableUpdate = obj - .Select(i => CheckForUpdateResult(i, minVersion, assetFilename, packageName, targetFilename)) - .Where(i => i != null) - .OrderByDescending(i => Version.Parse(i.AvailableVersion)) - .FirstOrDefault(); - - return availableUpdate ?? new CheckForUpdateResult - { - IsUpdateAvailable = false - }; - } - - private bool MatchesUpdateLevel(RootObject i, PackageVersionClass updateLevel) - { - if (updateLevel == PackageVersionClass.Beta) - { - return i.prerelease && i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase); - } - if (updateLevel == PackageVersionClass.Dev) - { - return !i.prerelease || i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase) || - i.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase); - } - - // Technically all we need to do is check that it's not pre-release - // But let's addititional checks for -beta and -dev to handle builds that might be temporarily tagged incorrectly. - return !i.prerelease && !i.name.EndsWith("-beta", StringComparison.OrdinalIgnoreCase) && - !i.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase); - } - - public async Task<List<RootObject>> GetLatestReleases(string organzation, string repository, string assetFilename, CancellationToken cancellationToken) - { - var list = new List<RootObject>(); - - var url = string.Format("https://api.github.com/repos/{0}/{1}/releases", organzation, repository); - - var options = new HttpRequestOptions - { - Url = url, - EnableKeepAlive = false, - CancellationToken = cancellationToken, - UserAgent = "Emby/3.0", - BufferContent = false - }; - - using (var response = await _httpClient.SendAsync(options, "GET").ConfigureAwait(false)) - using (var stream = response.Content) - { - var obj = await _jsonSerializer.DeserializeFromStreamAsync<RootObject[]>(stream).ConfigureAwait(false); - - obj = obj.Where(i => (i.assets ?? new List<Asset>()).Any(a => IsAsset(a, assetFilename, i.tag_name))).ToArray(); - - list.AddRange(obj.Where(i => MatchesUpdateLevel(i, PackageVersionClass.Release)).OrderByDescending(GetVersion).Take(1)); - list.AddRange(obj.Where(i => MatchesUpdateLevel(i, PackageVersionClass.Beta)).OrderByDescending(GetVersion).Take(1)); - list.AddRange(obj.Where(i => MatchesUpdateLevel(i, PackageVersionClass.Dev)).OrderByDescending(GetVersion).Take(1)); - - return list; - } - } - - public Version GetVersion(RootObject obj) - { - Version version; - if (!Version.TryParse(obj.tag_name, out version)) - { - return new Version(1, 0); - } - - return version; - } - - private CheckForUpdateResult CheckForUpdateResult(RootObject obj, Version minVersion, string assetFilename, string packageName, string targetFilename) - { - Version version; - var versionString = obj.tag_name; - if (!Version.TryParse(versionString, out version)) - { - return null; - } - - if (version < minVersion) - { - return null; - } - - var asset = (obj.assets ?? new List<Asset>()).FirstOrDefault(i => IsAsset(i, assetFilename, versionString)); - - if (asset == null) - { - return null; - } - - return new CheckForUpdateResult - { - AvailableVersion = version.ToString(), - IsUpdateAvailable = version > minVersion, - Package = new PackageVersionInfo - { - classification = obj.prerelease ? - (obj.name.EndsWith("-dev", StringComparison.OrdinalIgnoreCase) ? PackageVersionClass.Dev : PackageVersionClass.Beta) : - PackageVersionClass.Release, - name = packageName, - sourceUrl = asset.browser_download_url, - targetFilename = targetFilename, - versionStr = version.ToString(), - requiredVersionStr = "1.0.0", - description = obj.body, - infoUrl = obj.html_url - } - }; - } - - private bool IsAsset(Asset asset, string assetFilename, string version) - { - var downloadFilename = Path.GetFileName(asset.browser_download_url) ?? string.Empty; - - assetFilename = assetFilename.Replace("{version}", version); - - if (downloadFilename.IndexOf(assetFilename, StringComparison.OrdinalIgnoreCase) != -1) - { - return true; - } - - return string.Equals(assetFilename, downloadFilename, StringComparison.OrdinalIgnoreCase); - } - - public class Uploader - { - public string login { get; set; } - public int id { get; set; } - public string avatar_url { get; set; } - public string gravatar_id { get; set; } - public string url { get; set; } - public string html_url { get; set; } - public string followers_url { get; set; } - public string following_url { get; set; } - public string gists_url { get; set; } - public string starred_url { get; set; } - public string subscriptions_url { get; set; } - public string organizations_url { get; set; } - public string repos_url { get; set; } - public string events_url { get; set; } - public string received_events_url { get; set; } - public string type { get; set; } - public bool site_admin { get; set; } - } - - public class Asset - { - public string url { get; set; } - public int id { get; set; } - public string name { get; set; } - public object label { get; set; } - public Uploader uploader { get; set; } - public string content_type { get; set; } - public string state { get; set; } - public int size { get; set; } - public int download_count { get; set; } - public string created_at { get; set; } - public string updated_at { get; set; } - public string browser_download_url { get; set; } - } - - public class Author - { - public string login { get; set; } - public int id { get; set; } - public string avatar_url { get; set; } - public string gravatar_id { get; set; } - public string url { get; set; } - public string html_url { get; set; } - public string followers_url { get; set; } - public string following_url { get; set; } - public string gists_url { get; set; } - public string starred_url { get; set; } - public string subscriptions_url { get; set; } - public string organizations_url { get; set; } - public string repos_url { get; set; } - public string events_url { get; set; } - public string received_events_url { get; set; } - public string type { get; set; } - public bool site_admin { get; set; } - } - - public class RootObject - { - public string url { get; set; } - public string assets_url { get; set; } - public string upload_url { get; set; } - public string html_url { get; set; } - public int id { get; set; } - public string tag_name { get; set; } - public string target_commitish { get; set; } - public string name { get; set; } - public bool draft { get; set; } - public Author author { get; set; } - public bool prerelease { get; set; } - public string created_at { get; set; } - public string published_at { get; set; } - public List<Asset> assets { get; set; } - public string tarball_url { get; set; } - public string zipball_url { get; set; } - public string body { get; set; } - } - } -} diff --git a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs index fb131f304..b68961889 100644 --- a/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs +++ b/MediaBrowser.MediaEncoding/Encoder/EncoderValidator.cs @@ -1,7 +1,8 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Globalization; +using System.Linq; +using System.Text.RegularExpressions; using MediaBrowser.Model.Diagnostics; using Microsoft.Extensions.Logging; @@ -18,21 +19,21 @@ namespace MediaBrowser.MediaEncoding.Encoder _processFactory = processFactory; } - public Tuple<List<string>, List<string>> Validate(string encoderPath) + public (IEnumerable<string> decoders, IEnumerable<string> encoders) Validate(string encoderPath) { - _logger.LogInformation("Validating media encoder at {0}", encoderPath); + _logger.LogInformation("Validating media encoder at {EncoderPath}", encoderPath); - var decoders = GetDecoders(encoderPath); - var encoders = GetEncoders(encoderPath); + var decoders = GetCodecs(encoderPath, Codec.Decoder); + var encoders = GetCodecs(encoderPath, Codec.Encoder); _logger.LogInformation("Encoder validation complete"); - return new Tuple<List<string>, List<string>>(decoders, encoders); + return (decoders, encoders); } public bool ValidateVersion(string encoderAppPath, bool logOutput) { - string output = string.Empty; + string output = null; try { output = GetProcessOutput(encoderAppPath, "-version"); @@ -71,20 +72,7 @@ namespace MediaBrowser.MediaEncoding.Encoder return true; } - private List<string> GetDecoders(string encoderAppPath) - { - string output = string.Empty; - try - { - output = GetProcessOutput(encoderAppPath, "-decoders"); - } - catch (Exception ex) - { - _logger.LogError(ex, "Error detecting available decoders"); - } - - var found = new List<string>(); - var required = new[] + private static readonly string[] requiredDecoders = new[] { "mpeg2video", "h264_qsv", @@ -101,33 +89,7 @@ namespace MediaBrowser.MediaEncoding.Encoder "hevc" }; - foreach (var codec in required) - { - var srch = " " + codec + " "; - - if (output.IndexOf(srch, StringComparison.OrdinalIgnoreCase) != -1) - { - _logger.LogInformation("Decoder available: " + codec); - found.Add(codec); - } - } - - return found; - } - - private List<string> GetEncoders(string encoderAppPath) - { - string output = null; - try - { - output = GetProcessOutput(encoderAppPath, "-encoders"); - } - catch - { - } - - var found = new List<string>(); - var required = new[] + private static readonly string[] requiredEncoders = new[] { "libx264", "libx265", @@ -151,32 +113,46 @@ namespace MediaBrowser.MediaEncoding.Encoder "ac3" }; - output = output ?? string.Empty; + private enum Codec + { + Encoder, + Decoder + } - var index = 0; + private IEnumerable<string> GetCodecs(string encoderAppPath, Codec codec) + { + string codecstr = codec == Codec.Encoder ? "encoders" : "decoders"; + string output = null; + try + { + output = GetProcessOutput(encoderAppPath, "-" + codecstr); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error detecting available {Codec}", codecstr); + } - foreach (var codec in required) + if (string.IsNullOrWhiteSpace(output)) { - var srch = " " + codec + " "; + return Enumerable.Empty<string>(); + } - if (output.IndexOf(srch, StringComparison.OrdinalIgnoreCase) != -1) - { - if (index < required.Length - 1) - { - _logger.LogInformation("Encoder available: " + codec); - } + var required = codec == Codec.Encoder ? requiredEncoders : requiredDecoders; - found.Add(codec); - } - index++; - } + var found = Regex + .Matches(output, @"^\s\S{6}\s(?<codec>[\w|-]+)\s+.+$", RegexOptions.Multiline) + .Cast<Match>() + .Select(x => x.Groups["codec"].Value) + .Where(x => required.Contains(x)); + + _logger.LogInformation("Available {Codec}: {Codecs}", codecstr, found); return found; } private string GetProcessOutput(string path, string arguments) { - var process = _processFactory.Create(new ProcessOptions + IProcess process = _processFactory.Create(new ProcessOptions { CreateNoWindow = true, UseShellExecute = false, @@ -187,7 +163,7 @@ namespace MediaBrowser.MediaEncoding.Encoder RedirectStandardOutput = true }); - _logger.LogInformation("Running {path} {arguments}", path, arguments); + _logger.LogInformation("Running {Path} {Arguments}", path, arguments); using (process) { diff --git a/MediaBrowser.MediaEncoding/Encoder/FontConfigLoader.cs b/MediaBrowser.MediaEncoding/Encoder/FontConfigLoader.cs deleted file mode 100644 index c62de0b11..000000000 --- a/MediaBrowser.MediaEncoding/Encoder/FontConfigLoader.cs +++ /dev/null @@ -1,179 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; -using MediaBrowser.Common.Progress; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Net; -using Microsoft.Extensions.Logging; - -namespace MediaBrowser.MediaEncoding.Encoder -{ - public class FontConfigLoader - { - private readonly IHttpClient _httpClient; - private readonly IApplicationPaths _appPaths; - private readonly ILogger _logger; - private readonly IZipClient _zipClient; - private readonly IFileSystem _fileSystem; - - private readonly string[] _fontUrls = - { - "https://github.com/MediaBrowser/MediaBrowser.Resources/raw/master/ffmpeg/ARIALUNI.7z" - }; - - public FontConfigLoader(IHttpClient httpClient, IApplicationPaths appPaths, ILogger logger, IZipClient zipClient, IFileSystem fileSystem) - { - _httpClient = httpClient; - _appPaths = appPaths; - _logger = logger; - _zipClient = zipClient; - _fileSystem = fileSystem; - } - - /// <summary> - /// Extracts the fonts. - /// </summary> - /// <param name="targetPath">The target path.</param> - /// <returns>Task.</returns> - public async Task DownloadFonts(string targetPath) - { - try - { - var fontsDirectory = Path.Combine(targetPath, "fonts"); - - _fileSystem.CreateDirectory(fontsDirectory); - - const string fontFilename = "ARIALUNI.TTF"; - - var fontFile = Path.Combine(fontsDirectory, fontFilename); - - if (_fileSystem.FileExists(fontFile)) - { - await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false); - } - else - { - // Kick this off, but no need to wait on it - var task = Task.Run(async () => - { - await DownloadFontFile(fontsDirectory, fontFilename, new SimpleProgress<double>()).ConfigureAwait(false); - - await WriteFontConfigFile(fontsDirectory).ConfigureAwait(false); - }); - } - } - catch (HttpException ex) - { - // Don't let the server crash because of this - _logger.LogError(ex, "Error downloading ffmpeg font files"); - } - catch (Exception ex) - { - // Don't let the server crash because of this - _logger.LogError(ex, "Error writing ffmpeg font files"); - } - } - - /// <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, IProgress<double> progress) - { - var existingFile = _fileSystem - .GetFilePaths(_appPaths.ProgramDataPath, true) - .FirstOrDefault(i => string.Equals(fontFilename, Path.GetFileName(i), StringComparison.OrdinalIgnoreCase)); - - if (existingFile != null) - { - try - { - _fileSystem.CopyFile(existingFile, Path.Combine(fontsDirectory, fontFilename), true); - return; - } - catch (IOException ex) - { - // Log this, but don't let it fail the operation - _logger.LogError(ex, "Error copying file"); - } - } - - string tempFile = null; - - foreach (var url in _fontUrls) - { - progress.Report(0); - - try - { - tempFile = await _httpClient.GetTempFile(new HttpRequestOptions - { - Url = url, - Progress = progress - - }).ConfigureAwait(false); - - break; - } - catch (Exception ex) - { - // The core can function without the font file, so handle this - _logger.LogError(ex, "Failed to download ffmpeg font file from {url}", url); - } - } - - if (string.IsNullOrEmpty(tempFile)) - { - return; - } - - Extract7zArchive(tempFile, fontsDirectory); - - try - { - _fileSystem.DeleteFile(tempFile); - } - catch (IOException ex) - { - // Log this, but don't let it fail the operation - _logger.LogError(ex, "Error deleting temp file {path}", tempFile); - } - } - private void Extract7zArchive(string archivePath, string targetPath) - { - _logger.LogInformation("Extracting {ArchivePath} to {TargetPath}", archivePath, targetPath); - - _zipClient.ExtractAllFrom7z(archivePath, targetPath, true); - } - - /// <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 (!_fileSystem.FileExists(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 = _fileSystem.GetFileStream(fontConfigFile, FileOpenMode.Create, FileAccessMode.Write, - FileShareMode.Read, true)) - { - await fileStream.WriteAsync(bytes, 0, bytes.Length); - } - } - } - } -} diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs index 181fc0f65..a93dd9742 100644 --- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs +++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs @@ -70,13 +70,27 @@ namespace MediaBrowser.MediaEncoding.Encoder private readonly string _originalFFMpegPath; private readonly string _originalFFProbePath; private readonly int DefaultImageExtractionTimeoutMs; - private readonly bool EnableEncoderFontFile; - private readonly IEnvironmentInfo _environmentInfo; - public MediaEncoder(ILogger logger, IJsonSerializer jsonSerializer, string ffMpegPath, string ffProbePath, bool hasExternalEncoder, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILiveTvManager liveTvManager, IIsoManager isoManager, ILibraryManager libraryManager, IChannelManager channelManager, ISessionManager sessionManager, Func<ISubtitleEncoder> subtitleEncoder, Func<IMediaSourceManager> mediaSourceManager, IHttpClient httpClient, IZipClient zipClient, IProcessFactory processFactory, + public MediaEncoder(ILogger logger, + IJsonSerializer jsonSerializer, + string ffMpegPath, + string ffProbePath, + bool hasExternalEncoder, + IServerConfigurationManager configurationManager, + IFileSystem fileSystem, + ILiveTvManager liveTvManager, + IIsoManager isoManager, + ILibraryManager libraryManager, + IChannelManager channelManager, + ISessionManager sessionManager, + Func<ISubtitleEncoder> subtitleEncoder, + Func<IMediaSourceManager> mediaSourceManager, + IHttpClient httpClient, + IZipClient zipClient, + IProcessFactory processFactory, int defaultImageExtractionTimeoutMs, - bool enableEncoderFontFile, IEnvironmentInfo environmentInfo) + IEnvironmentInfo environmentInfo) { _logger = logger; _jsonSerializer = jsonSerializer; @@ -93,7 +107,6 @@ namespace MediaBrowser.MediaEncoding.Encoder _zipClient = zipClient; _processFactory = processFactory; DefaultImageExtractionTimeoutMs = defaultImageExtractionTimeoutMs; - EnableEncoderFontFile = enableEncoderFontFile; _environmentInfo = environmentInfo; FFProbePath = ffProbePath; FFMpegPath = ffMpegPath; @@ -175,18 +188,8 @@ namespace MediaBrowser.MediaEncoding.Encoder { var result = new EncoderValidator(_logger, _processFactory).Validate(FFMpegPath); - SetAvailableDecoders(result.Item1); - SetAvailableEncoders(result.Item2); - - if (EnableEncoderFontFile) - { - var directory = FileSystem.GetDirectoryName(FFMpegPath); - - if (!string.IsNullOrWhiteSpace(directory) && FileSystem.ContainsSubPath(ConfigurationManager.ApplicationPaths.ProgramDataPath, directory)) - { - new FontConfigLoader(_httpClient, ConfigurationManager.ApplicationPaths, _logger, _zipClient, FileSystem).DownloadFonts(directory).ConfigureAwait(false); - } - } + SetAvailableDecoders(result.decoders); + SetAvailableEncoders(result.encoders); } } @@ -401,14 +404,14 @@ namespace MediaBrowser.MediaEncoding.Encoder } private List<string> _encoders = new List<string>(); - public void SetAvailableEncoders(List<string> list) + public void SetAvailableEncoders(IEnumerable<string> list) { _encoders = list.ToList(); //_logger.Info("Supported encoders: {0}", string.Join(",", list.ToArray())); } private List<string> _decoders = new List<string>(); - public void SetAvailableDecoders(List<string> list) + public void SetAvailableDecoders(IEnumerable<string> list) { _decoders = list.ToList(); //_logger.Info("Supported decoders: {0}", string.Join(",", list.ToArray())); |
