Merge branch 'master' into fix-env

This commit is contained in:
Joshua M. Boniface 2019-02-03 22:34:40 -05:00 committed by GitHub
commit 20033f2275
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
70 changed files with 495 additions and 440 deletions

View File

@ -15,6 +15,7 @@
- [cvium](https://github.com/cvium)
- [wtayl0r](https://github.com/wtayl0r)
- [TtheCreator](https://github.com/Tthecreator)
- [dkanada](https://github.com/dkanada)
- [LogicalPhallacy](https://github.com/LogicalPhallacy/)
- [RazeLighter777](https://github.com/RazeLighter777)

View File

@ -4,6 +4,7 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Emby.Dlna.Profiles;
using Emby.Dlna.Server;
using MediaBrowser.Common.Configuration;
@ -48,11 +49,11 @@ namespace Emby.Dlna
_assemblyInfo = assemblyInfo;
}
public void InitProfiles()
public async Task InitProfilesAsync()
{
try
{
ExtractSystemProfiles();
await ExtractSystemProfilesAsync();
LoadProfiles();
}
catch (Exception ex)
@ -359,7 +360,7 @@ namespace Emby.Dlna
};
}
private void ExtractSystemProfiles()
private async Task ExtractSystemProfilesAsync()
{
var namespaceName = GetType().Namespace + ".Profiles.Xml.";
@ -383,7 +384,7 @@ namespace Emby.Dlna
using (var fileStream = _fileSystem.GetFileStream(path, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
{
stream.CopyTo(fileStream);
await stream.CopyToAsync(fileStream);
}
}
}

View File

@ -125,9 +125,9 @@ namespace Emby.Dlna.Main
Current = this;
}
public void Run()
public async Task RunAsync()
{
((DlnaManager)_dlnaManager).InitProfiles();
await ((DlnaManager)_dlnaManager).InitProfilesAsync().ConfigureAwait(false);
ReloadComponents();

View File

@ -71,12 +71,14 @@ namespace Emby.Notifications
_coreNotificationTypes = new CoreNotificationTypes(localization, appHost).GetNotificationTypes().Select(i => i.Type).ToArray();
}
public void Run()
public Task RunAsync()
{
_libraryManager.ItemAdded += _libraryManager_ItemAdded;
_appHost.HasPendingRestartChanged += _appHost_HasPendingRestartChanged;
_appHost.HasUpdateAvailableChanged += _appHost_HasUpdateAvailableChanged;
_activityManager.EntryCreated += _activityManager_EntryCreated;
return Task.CompletedTask;
}
private async void _appHost_HasPendingRestartChanged(object sender, EventArgs e)

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.Updates;
@ -58,7 +59,7 @@ namespace Emby.Server.Implementations.Activity
_deviceManager = deviceManager;
}
public void Run()
public Task RunAsync()
{
_taskManager.TaskCompleted += _taskManager_TaskCompleted;
@ -90,6 +91,8 @@ namespace Emby.Server.Implementations.Activity
_deviceManager.CameraImageUploaded += _deviceManager_CameraImageUploaded;
_appHost.ApplicationUpdated += _appHost_ApplicationUpdated;
return Task.CompletedTask;
}
void _deviceManager_CameraImageUploaded(object sender, GenericEventArgs<CameraImageUploadInfo> e)

View File

@ -110,7 +110,6 @@ using MediaBrowser.XbmcMetadata.Providers;
using Microsoft.Extensions.Logging;
using ServiceStack;
using ServiceStack.Text.Jsv;
using StringExtensions = MediaBrowser.Controller.Extensions.StringExtensions;
using X509Certificate = System.Security.Cryptography.X509Certificates.X509Certificate;
namespace Emby.Server.Implementations
@ -302,7 +301,7 @@ namespace Emby.Server.Implementations
private ILiveTvManager LiveTvManager { get; set; }
public ILocalizationManager LocalizationManager { get; set; }
public LocalizationManager LocalizationManager { get; set; }
private IEncodingManager EncodingManager { get; set; }
private IChannelManager ChannelManager { get; set; }
@ -646,8 +645,10 @@ namespace Emby.Server.Implementations
/// <summary>
/// Runs the startup tasks.
/// </summary>
public Task RunStartupTasks()
public async Task RunStartupTasks()
{
Logger.LogInformation("Running startup tasks");
Resolve<ITaskManager>().AddTasks(GetExports<IScheduledTask>(false));
ConfigurationManager.ConfigurationUpdated += OnConfigurationUpdated;
@ -666,20 +667,20 @@ namespace Emby.Server.Implementations
Logger.LogInformation("ServerId: {0}", SystemId);
var entryPoints = GetExports<IServerEntryPoint>();
RunEntryPoints(entryPoints, true);
var now = DateTime.UtcNow;
await Task.WhenAll(StartEntryPoints(entryPoints, true));
Logger.LogInformation("Executed all pre-startup entry points in {Elapsed:fff} ms", DateTime.Now - now);
Logger.LogInformation("Core startup complete");
HttpServer.GlobalResponse = null;
Logger.LogInformation("Post-init migrations complete");
RunEntryPoints(entryPoints, false);
Logger.LogInformation("All entry points have started");
return Task.CompletedTask;
now = DateTime.UtcNow;
await Task.WhenAll(StartEntryPoints(entryPoints, false));
Logger.LogInformation("Executed all post-startup entry points in {Elapsed:fff} ms", DateTime.Now - now);
}
private void RunEntryPoints(IEnumerable<IServerEntryPoint> entryPoints, bool isBeforeStartup)
private IEnumerable<Task> StartEntryPoints(IEnumerable<IServerEntryPoint> entryPoints, bool isBeforeStartup)
{
foreach (var entryPoint in entryPoints)
{
@ -688,22 +689,13 @@ namespace Emby.Server.Implementations
continue;
}
var name = entryPoint.GetType().FullName;
Logger.LogInformation("Starting entry point {Name}", name);
var now = DateTime.UtcNow;
try
{
entryPoint.Run();
}
catch (Exception ex)
{
Logger.LogError(ex, "Error while running entrypoint {Name}", name);
}
Logger.LogInformation("Entry point completed: {Name}. Duration: {Duration} seconds", name, (DateTime.UtcNow - now).TotalSeconds.ToString(CultureInfo.InvariantCulture), "ImageInfos");
Logger.LogDebug("Starting entry point {Type}", entryPoint.GetType());
yield return entryPoint.RunAsync();
}
}
public void Init()
public async Task Init()
{
HttpPort = ServerConfigurationManager.Configuration.HttpServerPortNumber;
HttpsPort = ServerConfigurationManager.Configuration.HttpsPortNumber;
@ -733,7 +725,7 @@ namespace Emby.Server.Implementations
SetHttpLimit();
RegisterResources();
await RegisterResources();
FindParts();
}
@ -748,7 +740,7 @@ namespace Emby.Server.Implementations
/// <summary>
/// Registers resources that classes will depend on
/// </summary>
protected void RegisterResources()
protected async Task RegisterResources()
{
RegisterSingleInstance(ConfigurationManager);
RegisterSingleInstance<IApplicationHost>(this);
@ -809,9 +801,9 @@ namespace Emby.Server.Implementations
IAssemblyInfo assemblyInfo = new AssemblyInfo();
RegisterSingleInstance(assemblyInfo);
LocalizationManager = new LocalizationManager(ServerConfigurationManager, FileSystemManager, JsonSerializer, LoggerFactory, assemblyInfo, new TextLocalizer());
StringExtensions.LocalizationManager = LocalizationManager;
RegisterSingleInstance(LocalizationManager);
LocalizationManager = new LocalizationManager(ServerConfigurationManager, FileSystemManager, JsonSerializer, LoggerFactory);
await LocalizationManager.LoadAll();
RegisterSingleInstance<ILocalizationManager>(LocalizationManager);
BlurayExaminer = new BdInfoExaminer(FileSystemManager);
RegisterSingleInstance(BlurayExaminer);

View File

@ -353,7 +353,7 @@ namespace Emby.Server.Implementations.Collections
_logger = logger;
}
public async void Run()
public async Task RunAsync()
{
if (!_config.Configuration.CollectionsUpgraded && _config.Configuration.IsStartupWizardCompleted)
{

View File

@ -425,7 +425,7 @@ namespace Emby.Server.Implementations.Devices
_logger = logger;
}
public async void Run()
public async Task RunAsync()
{
if (!_config.Configuration.CameraUploadUpgraded && _config.Configuration.IsStartupWizardCompleted)
{

View File

@ -37,12 +37,14 @@ namespace Emby.Server.Implementations.EntryPoints
_timerFactory = timerFactory;
}
public void Run()
public Task RunAsync()
{
if (_appHost.CanSelfRestart)
{
_appHost.HasPendingRestartChanged += _appHost_HasPendingRestartChanged;
}
return Task.CompletedTask;
}
void _appHost_HasPendingRestartChanged(object sender, EventArgs e)

View File

@ -61,17 +61,17 @@ namespace Emby.Server.Implementations.EntryPoints
return string.Join("|", values.ToArray());
}
void _config_ConfigurationUpdated(object sender, EventArgs e)
private async void _config_ConfigurationUpdated(object sender, EventArgs e)
{
if (!string.Equals(_lastConfigIdentifier, GetConfigIdentifier(), StringComparison.OrdinalIgnoreCase))
{
DisposeNat();
Run();
await RunAsync();
}
}
public void Run()
public Task RunAsync()
{
if (_config.Configuration.EnableUPnP && _config.Configuration.EnableRemoteAccess)
{
@ -80,6 +80,8 @@ namespace Emby.Server.Implementations.EntryPoints
_config.ConfigurationUpdated -= _config_ConfigurationUpdated;
_config.ConfigurationUpdated += _config_ConfigurationUpdated;
return Task.CompletedTask;
}
private void Start()

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
@ -65,7 +66,7 @@ namespace Emby.Server.Implementations.EntryPoints
_providerManager = providerManager;
}
public void Run()
public Task RunAsync()
{
_libraryManager.ItemAdded += libraryManager_ItemAdded;
_libraryManager.ItemUpdated += libraryManager_ItemUpdated;
@ -74,6 +75,8 @@ namespace Emby.Server.Implementations.EntryPoints
_providerManager.RefreshCompleted += _providerManager_RefreshCompleted;
_providerManager.RefreshStarted += _providerManager_RefreshStarted;
_providerManager.RefreshProgress += _providerManager_RefreshProgress;
return Task.CompletedTask;
}
private Dictionary<Guid, DateTime> _lastProgressMessageTimes = new Dictionary<Guid, DateTime>();

View File

@ -1,6 +1,7 @@
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Plugins;
@ -24,12 +25,14 @@ namespace Emby.Server.Implementations.EntryPoints
_liveTvManager = liveTvManager;
}
public void Run()
public Task RunAsync()
{
_liveTvManager.TimerCancelled += _liveTvManager_TimerCancelled;
_liveTvManager.SeriesTimerCancelled += _liveTvManager_SeriesTimerCancelled;
_liveTvManager.TimerCreated += _liveTvManager_TimerCreated;
_liveTvManager.SeriesTimerCreated += _liveTvManager_SeriesTimerCreated;
return Task.CompletedTask;
}
private void _liveTvManager_SeriesTimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.Updates;
using MediaBrowser.Controller;
@ -49,7 +50,7 @@ namespace Emby.Server.Implementations.EntryPoints
_sessionManager = sessionManager;
}
public void Run()
public Task RunAsync()
{
_userManager.UserDeleted += userManager_UserDeleted;
_userManager.UserUpdated += userManager_UserUpdated;
@ -65,6 +66,8 @@ namespace Emby.Server.Implementations.EntryPoints
_installationManager.PackageInstallationFailed += _installationManager_PackageInstallationFailed;
_taskManager.TaskCompleted += _taskManager_TaskCompleted;
return Task.CompletedTask;
}
void _installationManager_PackageInstalling(object sender, InstallationEventArgs e)

View File

@ -1,3 +1,4 @@
using System.Threading.Tasks;
using Emby.Server.Implementations.Browser;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
@ -32,11 +33,11 @@ namespace Emby.Server.Implementations.EntryPoints
/// <summary>
/// Runs this instance.
/// </summary>
public void Run()
public Task RunAsync()
{
if (!_appHost.CanLaunchWebBrowser)
{
return;
return Task.CompletedTask;
}
if (!_config.Configuration.IsStartupWizardCompleted)
@ -52,6 +53,8 @@ namespace Emby.Server.Implementations.EntryPoints
BrowserLauncher.OpenWebApp(_appHost);
}
}
return Task.CompletedTask;
}
/// <summary>

View File

@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using Emby.Server.Implementations.Udp;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Plugins;
@ -43,7 +44,7 @@ namespace Emby.Server.Implementations.EntryPoints
/// <summary>
/// Runs this instance.
/// </summary>
public void Run()
public Task RunAsync()
{
var udpServer = new UdpServer(_logger, _appHost, _json, _socketFactory);
@ -57,6 +58,8 @@ namespace Emby.Server.Implementations.EntryPoints
{
_logger.LogError(ex, "Failed to start UDP Server");
}
return Task.CompletedTask;
}
/// <summary>

View File

@ -38,9 +38,11 @@ namespace Emby.Server.Implementations.EntryPoints
_timerFactory = timerFactory;
}
public void Run()
public Task RunAsync()
{
_userDataManager.UserDataSaved += _userDataManager_UserDataSaved;
return Task.CompletedTask;
}
void _userDataManager_UserDataSaved(object sender, UserDataSaveEventArgs e)

View File

@ -633,9 +633,10 @@ namespace Emby.Server.Implementations.IO
_monitor = monitor;
}
public void Run()
public Task RunAsync()
{
_monitor.Start();
return Task.CompletedTask;
}
public void Dispose()

View File

@ -322,18 +322,18 @@ namespace Emby.Server.Implementations.Library
private string[] NormalizeLanguage(string language)
{
if (language != null)
if (language == null)
{
var culture = _localizationManager.FindLanguageInfo(language);
if (culture != null)
{
return culture.ThreeLetterISOLanguageNames;
}
return new string[] { language };
return Array.Empty<string>();
}
return Array.Empty<string>();
var culture = _localizationManager.FindLanguageInfo(language);
if (culture != null)
{
return culture.ThreeLetterISOLanguageNames;
}
return new string[] { language };
}
private void SetDefaultSubtitleStreamIndex(MediaSourceInfo source, UserItemData userData, User user, bool allowRememberingSelection)

View File

@ -1182,9 +1182,11 @@ namespace Emby.Server.Implementations.Library
_sessionManager = sessionManager;
}
public void Run()
public Task RunAsync()
{
_userManager.UserPolicyUpdated += _userManager_UserPolicyUpdated;
return Task.CompletedTask;
}
private void _userManager_UserPolicyUpdated(object sender, GenericEventArgs<User> e)

View File

@ -123,7 +123,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
}
}
public async void Start()
public async Task Start()
{
_timerProvider.RestartTimers();

View File

@ -1,12 +1,13 @@
using System.Threading.Tasks;
using MediaBrowser.Controller.Plugins;
namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
public class EntryPoint : IServerEntryPoint
{
public void Run()
public Task RunAsync()
{
EmbyTV.Current.Start();
return EmbyTV.Current.Start();
}
public void Dispose()

File diff suppressed because one or more lines are too long

View File

@ -1,63 +0,0 @@
using System;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace Emby.Server.Implementations.Localization
{
public class TextLocalizer : ITextLocalizer
{
public string RemoveDiacritics(string text)
{
if (text == null)
{
throw new ArgumentNullException(nameof(text));
}
var chars = Normalize(text, NormalizationForm.FormD)
.Where(ch => CharUnicodeInfo.GetUnicodeCategory(ch) != UnicodeCategory.NonSpacingMark);
return Normalize(string.Concat(chars), NormalizationForm.FormC);
}
private static string Normalize(string text, NormalizationForm form, bool stripStringOnFailure = true)
{
if (stripStringOnFailure)
{
try
{
return text.Normalize(form);
}
catch (ArgumentException)
{
// will throw if input contains invalid unicode chars
// https://mnaoumov.wordpress.com/2014/06/14/stripping-invalid-characters-from-utf-16-strings/
text = StripInvalidUnicodeCharacters(text);
return Normalize(text, form, false);
}
}
try
{
return text.Normalize(form);
}
catch (ArgumentException)
{
// if it still fails, return the original text
return text;
}
}
private static string StripInvalidUnicodeCharacters(string str)
{
var invalidCharactersRegex = new Regex("([\ud800-\udbff](?![\udc00-\udfff]))|((?<![\ud800-\udbff])[\udc00-\udfff])");
return invalidCharactersRegex.Replace(str, "");
}
public string NormalizeFormKD(string text)
{
return text.Normalize(NormalizationForm.FormKD);
}
}
}

View File

@ -68,8 +68,6 @@ namespace Emby.Server.Implementations.ScheduledTasks
};
}
public string Key => "RefreshChapterImages";
/// <summary>
/// Returns the task to be executed
/// </summary>
@ -161,22 +159,18 @@ namespace Emby.Server.Implementations.ScheduledTasks
}
}
/// <summary>
/// Gets the name of the task
/// </summary>
/// <value>The name.</value>
public string Name => "Chapter image extraction";
/// <summary>
/// Gets the description.
/// </summary>
/// <value>The description.</value>
public string Description => "Creates thumbnails for videos that have chapters.";
/// <summary>
/// Gets the category.
/// </summary>
/// <value>The category.</value>
public string Category => "Library";
public string Key => "RefreshChapterImages";
public bool IsHidden => false;
public bool IsEnabled => true;
public bool IsLogged => true;
}
}

View File

@ -158,31 +158,15 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
}
}
/// <summary>
/// Gets the name of the task
/// </summary>
/// <value>The name.</value>
public string Name => "Cache file cleanup";
public string Description => "Deletes cache files no longer needed by the system";
public string Category => "Maintenance";
public string Key => "DeleteCacheFiles";
/// <summary>
/// Gets the description.
/// </summary>
/// <value>The description.</value>
public string Description => "Deletes cache files no longer needed by the system";
/// <summary>
/// Gets the category.
/// </summary>
/// <value>The category.</value>
public string Category => "Maintenance";
/// <summary>
/// Gets a value indicating whether this instance is hidden.
/// </summary>
/// <value><c>true</c> if this instance is hidden; otherwise, <c>false</c>.</value>
public bool IsHidden => true;
public bool IsHidden => false;
public bool IsEnabled => true;

View File

@ -81,31 +81,15 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
return Task.CompletedTask;
}
public string Key => "CleanLogFiles";
/// <summary>
/// Gets the name of the task
/// </summary>
/// <value>The name.</value>
public string Name => "Log file cleanup";
/// <summary>
/// Gets the description.
/// </summary>
/// <value>The description.</value>
public string Description => string.Format("Deletes log files that are more than {0} days old.", ConfigurationManager.CommonConfiguration.LogFileRetentionDays);
/// <summary>
/// Gets the category.
/// </summary>
/// <value>The category.</value>
public string Category => "Maintenance";
/// <summary>
/// Gets a value indicating whether this instance is hidden.
/// </summary>
/// <value><c>true</c> if this instance is hidden; otherwise, <c>false</c>.</value>
public bool IsHidden => true;
public string Key => "CleanLogFiles";
public bool IsHidden => false;
public bool IsEnabled => true;

View File

@ -47,8 +47,6 @@ namespace Emby.Server.Implementations.ScheduledTasks
};
}
public string Key => "RefreshPeople";
/// <summary>
/// Returns the task to be executed
/// </summary>
@ -60,22 +58,18 @@ namespace Emby.Server.Implementations.ScheduledTasks
return _libraryManager.ValidatePeople(cancellationToken, progress);
}
/// <summary>
/// Gets the name of the task
/// </summary>
/// <value>The name.</value>
public string Name => "Refresh people";
/// <summary>
/// Gets the description.
/// </summary>
/// <value>The description.</value>
public string Description => "Updates metadata for actors and directors in your media library.";
/// <summary>
/// Gets the category.
/// </summary>
/// <value>The category.</value>
public string Category => "Library";
public string Key => "RefreshPeople";
public bool IsHidden => false;
public bool IsEnabled => true;
public bool IsLogged => true;
}
}

View File

@ -0,0 +1,119 @@
using MediaBrowser.Common;
using MediaBrowser.Common.Updates;
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;
using Microsoft.Extensions.Logging;
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}
};
}
/// <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(typeof(PluginUpdateTask).Assembly.GetName().Version, 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 {0}", package.name);
}
catch (IOException ex)
{
_logger.LogError(ex, "Error updating {0}", package.name);
}
// Update progress
lock (progress)
{
numComplete++;
progress.Report(90.0 * numComplete / packagesToInstall.Count + 10);
}
}
progress.Report(100);
}
public string Name => "Check for plugin updates";
public string Description => "Downloads and installs updates for plugins that are configured to update automatically.";
public string Category => "Application";
public string Key => "PluginUpdates";
public bool IsHidden => false;
public bool IsEnabled => true;
public bool IsLogged => true;
}
}

View File

@ -58,24 +58,18 @@ namespace Emby.Server.Implementations.ScheduledTasks
return ((LibraryManager)_libraryManager).ValidateMediaLibraryInternal(progress, cancellationToken);
}
/// <summary>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
public string Name => "Scan media library";
/// <summary>
/// Gets the description.
/// </summary>
/// <value>The description.</value>
public string Description => "Scans your media library and refreshes metatata based on configuration.";
/// <summary>
/// Gets the category.
/// </summary>
/// <value>The category.</value>
public string Category => "Library";
public string Key => "RefreshLibrary";
public bool IsHidden => false;
public bool IsEnabled => true;
public bool IsLogged => true;
}
}

View File

@ -164,15 +164,13 @@ namespace Emby.Server.Implementations.Updates
/// Gets all available packages.
/// </summary>
/// <returns>Task{List{PackageInfo}}.</returns>
public Task<List<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken,
public async Task<List<PackageInfo>> GetAvailablePackages(CancellationToken cancellationToken,
bool withRegistration = true,
string packageType = null,
Version applicationVersion = null)
{
// TODO cvium: when plugins get back this would need to be fixed
// var packages = await GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
return Task.FromResult(new List<PackageInfo>()); //FilterPackages(packages, packageType, applicationVersion);
var packages = await GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false);
return FilterPackages(packages, packageType, applicationVersion);
}
/// <summary>
@ -184,12 +182,10 @@ namespace Emby.Server.Implementations.Updates
{
using (var response = await _httpClient.SendAsync(new HttpRequestOptions
{
Url = "https://www.mb3admin.local/admin/service/EmbyPackages.json",
Url = "https://repo.jellyfin.org/releases/plugin/manifest.json",
CancellationToken = cancellationToken,
Progress = new SimpleProgress<double>(),
CacheLength = GetCacheLength(),
CacheMode = CacheMode.Unconditional
CacheLength = GetCacheLength()
}, "GET").ConfigureAwait(false))
{
using (var stream = response.Content)

View File

@ -114,12 +114,10 @@ namespace Jellyfin.Server
new NullImageEncoder(),
new NetworkManager(_loggerFactory, environmentInfo)))
{
appHost.Init();
await appHost.Init();
appHost.ImageProcessor.ImageEncoder = GetImageEncoder(fileSystem, appPaths, appHost.LocalizationManager);
_logger.LogInformation("Running startup tasks");
await appHost.RunStartupTasks();
// TODO: read input for a stop command
@ -133,8 +131,6 @@ namespace Jellyfin.Server
{
// Don't throw on cancellation
}
_logger.LogInformation("Disposing app host");
}
if (_restartOnShutdown)

View File

@ -130,7 +130,7 @@ namespace MediaBrowser.Api
/// <summary>
/// Runs this instance.
/// </summary>
public void Run()
public Task RunAsync()
{
try
{
@ -148,6 +148,8 @@ namespace MediaBrowser.Api
{
Logger.LogError(ex, "Error deleting encoded media cache");
}
return Task.CompletedTask;
}
public EncodingOptions GetEncodingOptions()
@ -162,8 +164,7 @@ namespace MediaBrowser.Api
{
var path = _config.ApplicationPaths.TranscodingTempPath;
foreach (var file in _fileSystem.GetFilePaths(path, true)
.ToList())
foreach (var file in _fileSystem.GetFilePaths(path, true))
{
_fileSystem.DeleteFile(file);
}

View File

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
@ -60,15 +61,15 @@ namespace MediaBrowser.Api
_fileSystem = fileSystem;
}
public object Get(GetMetadataEditorInfo request)
public async Task<object> Get(GetMetadataEditorInfo request)
{
var item = _libraryManager.GetItemById(request.ItemId);
var info = new MetadataEditorInfo
{
ParentalRatingOptions = _localizationManager.GetParentalRatings(),
ParentalRatingOptions = _localizationManager.GetParentalRatings().ToArray(),
ExternalIdInfos = _providerManager.GetExternalIdInfos(item).ToArray(),
Countries = _localizationManager.GetCountries(),
Countries = await _localizationManager.GetCountries(),
Cultures = _localizationManager.GetCultures()
};

View File

@ -89,7 +89,7 @@ namespace MediaBrowser.Common
/// <typeparam name="T"></typeparam>
/// <param name="manageLiftime">if set to <c>true</c> [manage liftime].</param>
/// <returns>IEnumerable{``0}.</returns>
IEnumerable<T> GetExports<T>(bool manageLiftime = true);
IEnumerable<T> GetExports<T>(bool manageLifetime = true);
/// <summary>
/// Updates the application.
@ -131,7 +131,7 @@ namespace MediaBrowser.Common
/// <summary>
/// Inits this instance.
/// </summary>
void Init();
Task Init();
/// <summary>
/// Creates the instance.

View File

@ -1,4 +1,8 @@
using MediaBrowser.Model.Globalization;
using System;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace MediaBrowser.Controller.Extensions
{
@ -7,11 +11,45 @@ namespace MediaBrowser.Controller.Extensions
/// </summary>
public static class StringExtensions
{
public static ILocalizationManager LocalizationManager { get; set; }
public static string RemoveDiacritics(this string text)
{
return LocalizationManager.RemoveDiacritics(text);
if (text == null)
{
throw new ArgumentNullException(nameof(text));
}
var chars = Normalize(text, NormalizationForm.FormD)
.Where(ch => CharUnicodeInfo.GetUnicodeCategory(ch) != UnicodeCategory.NonSpacingMark);
return Normalize(string.Concat(chars), NormalizationForm.FormC);
}
private static string Normalize(string text, NormalizationForm form, bool stripStringOnFailure = true)
{
if (stripStringOnFailure)
{
try
{
return text.Normalize(form);
}
catch (ArgumentException)
{
// will throw if input contains invalid unicode chars
// https://mnaoumov.wordpress.com/2014/06/14/stripping-invalid-characters-from-utf-16-strings/
text = Regex.Replace(text, "([\ud800-\udbff](?![\udc00-\udfff]))|((?<![\ud800-\udbff])[\udc00-\udfff])", "");
return Normalize(text, form, false);
}
}
try
{
return text.Normalize(form);
}
catch (ArgumentException)
{
// if it still fails, return the original text
return text;
}
}
}
}

View File

@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
namespace MediaBrowser.Controller.Plugins
{
@ -10,7 +11,7 @@ namespace MediaBrowser.Controller.Plugins
/// <summary>
/// Runs this instance.
/// </summary>
void Run();
Task RunAsync();
}
public interface IRunBeforeStartup

View File

@ -1,4 +1,6 @@
using System.Collections.Generic;
using System.Globalization;
using System.Threading.Tasks;
using MediaBrowser.Model.Entities;
namespace MediaBrowser.Model.Globalization
@ -17,12 +19,12 @@ namespace MediaBrowser.Model.Globalization
/// Gets the countries.
/// </summary>
/// <returns>IEnumerable{CountryInfo}.</returns>
CountryInfo[] GetCountries();
Task<CountryInfo[]> GetCountries();
/// <summary>
/// Gets the parental ratings.
/// </summary>
/// <returns>IEnumerable{ParentalRating}.</returns>
ParentalRating[] GetParentalRatings();
IEnumerable<ParentalRating> GetParentalRatings();
/// <summary>
/// Gets the rating level.
/// </summary>
@ -51,8 +53,6 @@ namespace MediaBrowser.Model.Globalization
/// <returns>IEnumerable{LocalizatonOption}.</returns>
LocalizationOption[] GetLocalizationOptions();
string RemoveDiacritics(string text);
string NormalizeFormKD(string text);
bool HasUnicodeCategory(string value, UnicodeCategory category);

View File

@ -566,8 +566,7 @@ namespace MediaBrowser.Providers.Manager
var providersWithChanges = providers
.Where(i =>
{
var hasFileChangeMonitor = i as IHasItemChangeMonitor;
if (hasFileChangeMonitor != null)
if (i is IHasItemChangeMonitor hasFileChangeMonitor)
{
return HasChanged(item, hasFileChangeMonitor, options.DirectoryService);
}

View File

@ -74,17 +74,12 @@ namespace MediaBrowser.Providers.MediaInfo
}
}
if (item.SupportsLocalMetadata)
if (item.SupportsLocalMetadata && video != null && !video.IsPlaceHolder
&& !video.SubtitleFiles.SequenceEqual(
_subtitleResolver.GetExternalSubtitleFiles(video, directoryService, false), StringComparer.Ordinal))
{
if (video != null && !video.IsPlaceHolder)
{
if (!video.SubtitleFiles
.SequenceEqual(_subtitleResolver.GetExternalSubtitleFiles(video, directoryService, false), StringComparer.Ordinal))
{
_logger.LogDebug("Refreshing {0} due to external subtitles change.", item.Path);
return true;
}
}
_logger.LogDebug("Refreshing {0} due to external subtitles change.", item.Path);
return true;
}
return false;

View File

@ -36,12 +36,6 @@ namespace MediaBrowser.Providers.MediaInfo
_json = json;
}
public string Name => "Download missing subtitles";
public string Description => "Searches the internet for missing subtitles based on metadata configuration.";
public string Category => "Library";
private SubtitleOptions GetOptions()
{
return _config.GetConfiguration<SubtitleOptions>("subtitles");
@ -204,6 +198,18 @@ namespace MediaBrowser.Providers.MediaInfo
};
}
public string Name => "Download missing subtitles";
public string Description => "Searches the internet for missing subtitles based on metadata configuration.";
public string Category => "Library";
public string Key => "DownloadSubtitles";
public bool IsHidden => false;
public bool IsEnabled => true;
public bool IsLogged => true;
}
}

View File

@ -425,11 +425,9 @@ namespace MediaBrowser.WebDashboard.Api
private async Task DumpFile(PackageCreator packageCreator, string resourceVirtualPath, string destinationFilePath, string mode, string appVersion)
{
using (var stream = await packageCreator.GetResource(resourceVirtualPath, mode, null, appVersion).ConfigureAwait(false))
using (var fs = _fileSystem.GetFileStream(destinationFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
{
using (var fs = _fileSystem.GetFileStream(destinationFilePath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
{
stream.CopyTo(fs);
}
await stream.CopyToAsync(fs);
}
}

View File

@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MediaBrowser.Common;
using MediaBrowser.Controller.Plugins;
@ -23,9 +24,11 @@ namespace MediaBrowser.WebDashboard
Instance = this;
}
public void Run()
public Task RunAsync()
{
PluginConfigurationPages = _appHost.GetExports<IPluginConfigurationPage>().ToList();
return Task.CompletedTask;
}
public void Dispose()

View File

@ -1,4 +1,5 @@
using System;
using System.Threading.Tasks;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
@ -28,9 +29,11 @@ namespace MediaBrowser.XbmcMetadata
_config = config;
}
public void Run()
public Task RunAsync()
{
_userDataManager.UserDataSaved += _userDataManager_UserDataSaved;
return Task.CompletedTask;
}
void _userDataManager_UserDataSaved(object sender, UserDataSaveEventArgs e)

View File

@ -68,8 +68,7 @@ new_version="$1"
# Parse the version from the AssemblyVersion
old_version="$(
grep "AssemblyVersion" ${shared_version_file} \
| sed -E 's/\[assembly: ?AssemblyVersion\("([0-9\.]+)"\)\]/\1/' \
| sed -E 's/.0$//'
| sed -E 's/\[assembly: ?AssemblyVersion\("([0-9\.]+)"\)\]/\1/'
)"
# Set the shared version to the specified new_version

View File

@ -0,0 +1,15 @@
FROM centos:7
ARG HOME=/build
RUN mkdir /build && \
yum install -y @buildsys-build rpmdevtools yum-plugins-core && \
rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm && \
rpmdev-setuptree
WORKDIR /build/rpmbuild
COPY ./deployment/centos-package-x64/pkg-src/jellyfin.spec SPECS
COPY ./deployment/centos-package-x64/pkg-src/ SOURCES
RUN spectool -g -R SPECS/jellyfin.spec && \
rpmbuild -bs SPECS/jellyfin.spec && \
yum-builddep -y SRPMS/jellyfin-*.src.rpm && \
rpmbuild -bb SPECS/jellyfin.spec;

View File

@ -0,0 +1 @@
../fedora-package-x64/clean.sh

View File

@ -0,0 +1 @@
../fedora-package-x64/package.sh

View File

@ -0,0 +1 @@
../fedora-package-x64/pkg-src

View File

@ -18,7 +18,7 @@
JELLYFIN_DATA_DIRECTORY="/var/lib/jellyfin"
JELLYFIN_CONFIG_DIRECTORY="/etc/jellyfin"
JELLYFIN_LOG_DIRECTORY="/var/log/jellyfin"
JELLYFIN_CACHE_DIRECTORY="/var/log/jellyfin"
JELLYFIN_CACHE_DIRECTORY="/var/cache/jellyfin"
# In-App service control
JELLYFIN_RESTART_OPT="--restartpath=/usr/libexec/jellyfin/restart.sh"

View File

@ -1,11 +1,11 @@
%global debug_package %{nil}
# jellyfin tag to package
%global gittag v10.1.0
# Taglib-sharp commit of the submodule since github archive doesn't include submodules
%global taglib_commit ee5ab21742b71fd1b87ee24895582327e9e04776
%global taglib_shortcommit %(c=%{taglib_commit}; echo ${c:0:7})
# Set the dotnet runtime
%if 0%{?fedora}
%global dotnet_runtime fedora-x64
%else
%global dotnet_runtime centos-x64
%endif
AutoReq: no
Name: jellyfin
Version: 10.1.0
Release: 1%{?dist}
@ -31,13 +31,11 @@ BuildRequires: dotnet-sdk-2.2
# RPMfusion free
Requires: ffmpeg
# For the update-db-paths.sh script to fix emby paths to jellyfin
%{?fedora:Recommends: sqlite}
# Fedora has openssl1.1 which is incompatible with dotnet
%{?fedora:Requires: compat-openssl10}
# Disable Automatic Dependency Processing for Centos
%{?el7:AutoReqProv: no}
# Disable Automatic Dependency Processing
AutoReqProv: no
%description
Jellyfin is a free software media system that puts you in control of managing and streaming your media.
@ -51,7 +49,7 @@ Jellyfin is a free software media system that puts you in control of managing an
%install
export DOTNET_CLI_TELEMETRY_OPTOUT=1
export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
dotnet publish --configuration Release --output='%{buildroot}%{_libdir}/jellyfin' --self-contained --runtime fedora-x64 Jellyfin.Server
dotnet publish --configuration Release --output='%{buildroot}%{_libdir}/jellyfin' --self-contained --runtime %{dotnet_runtime} Jellyfin.Server
%{__install} -D -m 0644 LICENSE %{buildroot}%{_datadir}/licenses/%{name}/LICENSE
%{__install} -D -m 0644 %{SOURCE5} %{buildroot}%{_sysconfdir}/systemd/system/%{name}.service.d/override.conf
%{__install} -D -m 0644 Jellyfin.Server/Resources/Configuration/logging.json %{buildroot}%{_sysconfdir}/%{name}/logging.json
@ -63,6 +61,7 @@ EOF
%{__mkdir} -p %{buildroot}%{_sharedstatedir}/jellyfin
%{__mkdir} -p %{buildroot}%{_sysconfdir}/%{name}
%{__mkdir} -p %{buildroot}%{_var}/log/jellyfin
%{__mkdir} -p %{buildroot}%{_var}/cache/jellyfin
%{__install} -D -m 0644 %{SOURCE1} %{buildroot}%{_unitdir}/%{name}.service
%{__install} -D -m 0644 %{SOURCE2} %{buildroot}%{_sysconfdir}/sysconfig/%{name}
@ -90,8 +89,9 @@ EOF
%config(noreplace) %attr(600,root,root) %{_sysconfdir}/sudoers.d/%{name}-sudoers
%config(noreplace) %{_sysconfdir}/systemd/system/%{name}.service.d/override.conf
%config(noreplace) %attr(644,jellyfin,jellyfin) %{_sysconfdir}/%{name}/logging.json
%attr(-,jellyfin,jellyfin) %dir %{_sharedstatedir}/jellyfin
%attr(750,jellyfin,jellyfin) %dir %{_sharedstatedir}/jellyfin
%attr(-,jellyfin,jellyfin) %dir %{_var}/log/jellyfin
%attr(750,jellyfin,jellyfin) %dir %{_var}/cache/jellyfin
%if 0%{?fedora}
%license LICENSE
%else
@ -106,7 +106,7 @@ getent passwd jellyfin >/dev/null || \
exit 0
%post
# Move existing configuration to /etc/jellyfin and symlink config to /etc/jellyfin
# Move existing configuration cache and logs to their new locations and symlink them.
if [ $1 -gt 1 ] ; then
service_state=$(systemctl is-active jellyfin.service)
if [ "${service_state}" = "active" ]; then
@ -122,6 +122,11 @@ if [ $1 -gt 1 ] ; then
rmdir %{_sharedstatedir}/%{name}/logs
ln -sf %{_var}/log/jellyfin %{_sharedstatedir}/%{name}/logs
fi
if [ ! -L %{_sharedstatedir}/%{name}/cache ]; then
mv %{_sharedstatedir}/%{name}/cache/* %{_var}/cache/jellyfin
rmdir %{_sharedstatedir}/%{name}/cache
ln -sf %{_var}/cache/jellyfin %{_sharedstatedir}/%{name}/cache
fi
if [ "${service_state}" = "active" ]; then
systemctl start jellyfin.service
fi