Register and construct IImageProcessor, SqliteItemRepository and IImageEncoder correctly

This commit is contained in:
Mark Monteiro 2020-04-04 17:12:24 -04:00
parent efe3ebaab8
commit 07cebbeae2
7 changed files with 38 additions and 57 deletions

View file

@ -33,7 +33,7 @@ namespace Emby.Drawing
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly IServerApplicationPaths _appPaths; private readonly IServerApplicationPaths _appPaths;
private readonly IImageEncoder _imageEncoder; private readonly IImageEncoder _imageEncoder;
private readonly Func<IMediaEncoder> _mediaEncoder; private readonly IMediaEncoder _mediaEncoder;
private bool _disposed = false; private bool _disposed = false;
@ -50,7 +50,7 @@ namespace Emby.Drawing
IServerApplicationPaths appPaths, IServerApplicationPaths appPaths,
IFileSystem fileSystem, IFileSystem fileSystem,
IImageEncoder imageEncoder, IImageEncoder imageEncoder,
Func<IMediaEncoder> mediaEncoder) IMediaEncoder mediaEncoder)
{ {
_logger = logger; _logger = logger;
_fileSystem = fileSystem; _fileSystem = fileSystem;
@ -359,13 +359,13 @@ namespace Emby.Drawing
{ {
string filename = (originalImagePath + dateModified.Ticks.ToString(CultureInfo.InvariantCulture)).GetMD5().ToString("N", CultureInfo.InvariantCulture); string filename = (originalImagePath + dateModified.Ticks.ToString(CultureInfo.InvariantCulture)).GetMD5().ToString("N", CultureInfo.InvariantCulture);
string cacheExtension = _mediaEncoder().SupportsEncoder("libwebp") ? ".webp" : ".png"; string cacheExtension = _mediaEncoder.SupportsEncoder("libwebp") ? ".webp" : ".png";
var outputPath = Path.Combine(_appPaths.ImageCachePath, "converted-images", filename + cacheExtension); var outputPath = Path.Combine(_appPaths.ImageCachePath, "converted-images", filename + cacheExtension);
var file = _fileSystem.GetFileInfo(outputPath); var file = _fileSystem.GetFileInfo(outputPath);
if (!file.Exists) if (!file.Exists)
{ {
await _mediaEncoder().ConvertImage(originalImagePath, outputPath).ConfigureAwait(false); await _mediaEncoder.ConvertImage(originalImagePath, outputPath).ConfigureAwait(false);
dateModified = _fileSystem.GetLastWriteTimeUtc(outputPath); dateModified = _fileSystem.GetLastWriteTimeUtc(outputPath);
} }
else else

View file

@ -48,6 +48,7 @@ using Emby.Server.Implementations.Session;
using Emby.Server.Implementations.SocketSharp; using Emby.Server.Implementations.SocketSharp;
using Emby.Server.Implementations.TV; using Emby.Server.Implementations.TV;
using Emby.Server.Implementations.Updates; using Emby.Server.Implementations.Updates;
using Jellyfin.Drawing.Skia;
using MediaBrowser.Api; using MediaBrowser.Api;
using MediaBrowser.Common; using MediaBrowser.Common;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
@ -262,8 +263,6 @@ namespace Emby.Server.Implementations
/// <value>The directory watchers.</value> /// <value>The directory watchers.</value>
private ILibraryMonitor LibraryMonitor { get; set; } private ILibraryMonitor LibraryMonitor { get; set; }
public IImageProcessor ImageProcessor { get; set; }
/// <summary> /// <summary>
/// Gets or sets the media encoder. /// Gets or sets the media encoder.
/// </summary> /// </summary>
@ -278,8 +277,6 @@ namespace Emby.Server.Implementations
/// <value>The user data repository.</value> /// <value>The user data repository.</value>
private IUserDataManager UserDataManager { get; set; } private IUserDataManager UserDataManager { get; set; }
internal SqliteItemRepository ItemRepository { get; set; }
private IAuthenticationRepository AuthenticationRepository { get; set; } private IAuthenticationRepository AuthenticationRepository { get; set; }
/// <summary> /// <summary>
@ -290,8 +287,6 @@ namespace Emby.Server.Implementations
public IStartupOptions StartupOptions { get; } public IStartupOptions StartupOptions { get; }
internal IImageEncoder ImageEncoder { get; private set; }
protected IProcessFactory ProcessFactory { get; private set; } protected IProcessFactory ProcessFactory { get; private set; }
protected readonly IXmlSerializer XmlSerializer; protected readonly IXmlSerializer XmlSerializer;
@ -316,7 +311,6 @@ namespace Emby.Server.Implementations
ILoggerFactory loggerFactory, ILoggerFactory loggerFactory,
IStartupOptions options, IStartupOptions options,
IFileSystem fileSystem, IFileSystem fileSystem,
IImageEncoder imageEncoder,
INetworkManager networkManager) INetworkManager networkManager)
{ {
XmlSerializer = new MyXmlSerializer(); XmlSerializer = new MyXmlSerializer();
@ -334,8 +328,6 @@ namespace Emby.Server.Implementations
StartupOptions = options; StartupOptions = options;
ImageEncoder = imageEncoder;
fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem)); fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem));
NetworkManager.NetworkChanged += OnNetworkChanged; NetworkManager.NetworkChanged += OnNetworkChanged;
@ -603,6 +595,11 @@ namespace Emby.Server.Implementations
/// </summary> /// </summary>
protected async Task RegisterServices(IServiceCollection serviceCollection, IConfiguration startupConfig) protected async Task RegisterServices(IServiceCollection serviceCollection, IConfiguration startupConfig)
{ {
var imageEncoderType = SkiaEncoder.IsNativeLibAvailable()
? typeof(SkiaEncoder)
: typeof(NullImageEncoder);
serviceCollection.AddSingleton(typeof(IImageEncoder), imageEncoderType);
serviceCollection.AddMemoryCache(); serviceCollection.AddMemoryCache();
serviceCollection.AddSingleton(ConfigurationManager); serviceCollection.AddSingleton(ConfigurationManager);
@ -672,8 +669,7 @@ namespace Emby.Server.Implementations
FileSystemManager); FileSystemManager);
serviceCollection.AddSingleton<IDisplayPreferencesRepository>(_displayPreferencesRepository); serviceCollection.AddSingleton<IDisplayPreferencesRepository>(_displayPreferencesRepository);
ItemRepository = new SqliteItemRepository(ServerConfigurationManager, this, LoggerFactory.CreateLogger<SqliteItemRepository>(), LocalizationManager); serviceCollection.AddSingleton<IItemRepository, SqliteItemRepository>();
serviceCollection.AddSingleton<IItemRepository>(ItemRepository);
AuthenticationRepository = GetAuthenticationRepository(); AuthenticationRepository = GetAuthenticationRepository();
serviceCollection.AddSingleton(AuthenticationRepository); serviceCollection.AddSingleton(AuthenticationRepository);
@ -685,7 +681,7 @@ namespace Emby.Server.Implementations
_userRepository, _userRepository,
XmlSerializer, XmlSerializer,
NetworkManager, NetworkManager,
() => ImageProcessor, Resolve<IImageProcessor>,
Resolve<IDtoService>, Resolve<IDtoService>,
this, this,
JsonSerializer, JsonSerializer,
@ -723,8 +719,7 @@ namespace Emby.Server.Implementations
serviceCollection.AddSingleton<IHttpListener, WebSocketSharpListener>(); serviceCollection.AddSingleton<IHttpListener, WebSocketSharpListener>();
serviceCollection.AddSingleton<IHttpServer, HttpListenerHost>(); serviceCollection.AddSingleton<IHttpServer, HttpListenerHost>();
ImageProcessor = new ImageProcessor(LoggerFactory.CreateLogger<ImageProcessor>(), ServerConfigurationManager.ApplicationPaths, FileSystemManager, ImageEncoder, () => MediaEncoder); serviceCollection.AddSingleton<IImageProcessor, ImageProcessor>();
serviceCollection.AddSingleton(ImageProcessor);
serviceCollection.AddSingleton<ITVSeriesManager, TVSeriesManager>(); serviceCollection.AddSingleton<ITVSeriesManager, TVSeriesManager>();
@ -797,8 +792,10 @@ namespace Emby.Server.Implementations
((UserManager)UserManager).Initialize(); ((UserManager)UserManager).Initialize();
((UserDataManager)UserDataManager).Repository = userDataRepo; ((UserDataManager)UserDataManager).Repository = userDataRepo;
ItemRepository.Initialize(userDataRepo, UserManager);
((LibraryManager)LibraryManager).ItemRepository = ItemRepository; var itemRepo = (SqliteItemRepository)Resolve<IItemRepository>();
itemRepo.Initialize(userDataRepo, UserManager);
((LibraryManager)LibraryManager).ItemRepository = itemRepo;
FindParts(); FindParts();
} }
@ -898,15 +895,13 @@ namespace Emby.Server.Implementations
/// </summary> /// </summary>
private void SetStaticProperties() private void SetStaticProperties()
{ {
ItemRepository.ImageProcessor = ImageProcessor;
// For now there's no real way to inject these properly // For now there's no real way to inject these properly
BaseItem.Logger = LoggerFactory.CreateLogger("BaseItem"); BaseItem.Logger = LoggerFactory.CreateLogger("BaseItem");
BaseItem.ConfigurationManager = ServerConfigurationManager; BaseItem.ConfigurationManager = ServerConfigurationManager;
BaseItem.LibraryManager = LibraryManager; BaseItem.LibraryManager = LibraryManager;
BaseItem.ProviderManager = Resolve<IProviderManager>(); BaseItem.ProviderManager = Resolve<IProviderManager>();
BaseItem.LocalizationManager = LocalizationManager; BaseItem.LocalizationManager = LocalizationManager;
BaseItem.ItemRepository = ItemRepository; BaseItem.ItemRepository = Resolve<IItemRepository>();
User.UserManager = UserManager; User.UserManager = UserManager;
BaseItem.FileSystem = FileSystemManager; BaseItem.FileSystem = FileSystemManager;
BaseItem.UserDataManager = UserDataManager; BaseItem.UserDataManager = UserDataManager;

View file

@ -39,12 +39,11 @@ namespace Emby.Server.Implementations.Data
{ {
private const string ChaptersTableName = "Chapters2"; private const string ChaptersTableName = "Chapters2";
/// <summary>
/// The _app paths
/// </summary>
private readonly IServerConfigurationManager _config; private readonly IServerConfigurationManager _config;
private readonly IServerApplicationHost _appHost; private readonly IServerApplicationHost _appHost;
private readonly ILocalizationManager _localization; private readonly ILocalizationManager _localization;
// TODO: Remove this dependency
private readonly IImageProcessor _imageProcessor;
private readonly TypeMapper _typeMapper; private readonly TypeMapper _typeMapper;
private readonly JsonSerializerOptions _jsonOptions; private readonly JsonSerializerOptions _jsonOptions;
@ -71,7 +70,8 @@ namespace Emby.Server.Implementations.Data
IServerConfigurationManager config, IServerConfigurationManager config,
IServerApplicationHost appHost, IServerApplicationHost appHost,
ILogger<SqliteItemRepository> logger, ILogger<SqliteItemRepository> logger,
ILocalizationManager localization) ILocalizationManager localization,
IImageProcessor imageProcessor)
: base(logger) : base(logger)
{ {
if (config == null) if (config == null)
@ -82,6 +82,7 @@ namespace Emby.Server.Implementations.Data
_config = config; _config = config;
_appHost = appHost; _appHost = appHost;
_localization = localization; _localization = localization;
_imageProcessor = imageProcessor;
_typeMapper = new TypeMapper(); _typeMapper = new TypeMapper();
_jsonOptions = JsonDefaults.GetOptions(); _jsonOptions = JsonDefaults.GetOptions();
@ -98,8 +99,6 @@ namespace Emby.Server.Implementations.Data
/// <inheritdoc /> /// <inheritdoc />
protected override TempStoreMode TempStore => TempStoreMode.Memory; protected override TempStoreMode TempStore => TempStoreMode.Memory;
public IImageProcessor ImageProcessor { get; set; }
/// <summary> /// <summary>
/// Opens the connection to the database /// Opens the connection to the database
/// </summary> /// </summary>
@ -1991,7 +1990,7 @@ namespace Emby.Server.Implementations.Data
if (!string.IsNullOrEmpty(chapter.ImagePath)) if (!string.IsNullOrEmpty(chapter.ImagePath))
{ {
chapter.ImageTag = ImageProcessor.GetImageCacheTag(item, chapter); chapter.ImageTag = _imageProcessor.GetImageCacheTag(item, chapter);
} }
} }

View file

@ -4,6 +4,7 @@
<ProjectReference Include="..\Emby.Naming\Emby.Naming.csproj" /> <ProjectReference Include="..\Emby.Naming\Emby.Naming.csproj" />
<ProjectReference Include="..\Emby.Notifications\Emby.Notifications.csproj" /> <ProjectReference Include="..\Emby.Notifications\Emby.Notifications.csproj" />
<ProjectReference Include="..\Jellyfin.Api\Jellyfin.Api.csproj" /> <ProjectReference Include="..\Jellyfin.Api\Jellyfin.Api.csproj" />
<ProjectReference Include="..\Jellyfin.Drawing.Skia\Jellyfin.Drawing.Skia.csproj" />
<ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" /> <ProjectReference Include="..\MediaBrowser.Model\MediaBrowser.Model.csproj" />
<ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj" /> <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj" />
<ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" /> <ProjectReference Include="..\MediaBrowser.Controller\MediaBrowser.Controller.csproj" />

View file

@ -78,12 +78,21 @@ namespace Jellyfin.Drawing.Skia
=> new HashSet<ImageFormat>() { ImageFormat.Webp, ImageFormat.Jpg, ImageFormat.Png }; => new HashSet<ImageFormat>() { ImageFormat.Webp, ImageFormat.Jpg, ImageFormat.Png };
/// <summary> /// <summary>
/// Test to determine if the native lib is available. /// Check if the native lib is available.
/// </summary> /// </summary>
public static void TestSkia() /// <returns>True if the native lib is available, otherwise false.</returns>
public static bool IsNativeLibAvailable()
{ {
// test an operation that requires the native library try
SKPMColor.PreMultiply(SKColors.Black); {
// test an operation that requires the native library
SKPMColor.PreMultiply(SKColors.Black);
return true;
}
catch (Exception)
{
return false;
}
} }
private static bool IsTransparent(SKColor color) private static bool IsTransparent(SKColor color)

View file

@ -20,21 +20,18 @@ namespace Jellyfin.Server
/// <param name="loggerFactory">The <see cref="ILoggerFactory" /> to be used by the <see cref="CoreAppHost" />.</param> /// <param name="loggerFactory">The <see cref="ILoggerFactory" /> to be used by the <see cref="CoreAppHost" />.</param>
/// <param name="options">The <see cref="StartupOptions" /> to be used by the <see cref="CoreAppHost" />.</param> /// <param name="options">The <see cref="StartupOptions" /> to be used by the <see cref="CoreAppHost" />.</param>
/// <param name="fileSystem">The <see cref="IFileSystem" /> to be used by the <see cref="CoreAppHost" />.</param> /// <param name="fileSystem">The <see cref="IFileSystem" /> to be used by the <see cref="CoreAppHost" />.</param>
/// <param name="imageEncoder">The <see cref="IImageEncoder" /> to be used by the <see cref="CoreAppHost" />.</param>
/// <param name="networkManager">The <see cref="INetworkManager" /> to be used by the <see cref="CoreAppHost" />.</param> /// <param name="networkManager">The <see cref="INetworkManager" /> to be used by the <see cref="CoreAppHost" />.</param>
public CoreAppHost( public CoreAppHost(
ServerApplicationPaths applicationPaths, ServerApplicationPaths applicationPaths,
ILoggerFactory loggerFactory, ILoggerFactory loggerFactory,
StartupOptions options, StartupOptions options,
IFileSystem fileSystem, IFileSystem fileSystem,
IImageEncoder imageEncoder,
INetworkManager networkManager) INetworkManager networkManager)
: base( : base(
applicationPaths, applicationPaths,
loggerFactory, loggerFactory,
options, options,
fileSystem, fileSystem,
imageEncoder,
networkManager) networkManager)
{ {
} }

View file

@ -183,7 +183,6 @@ namespace Jellyfin.Server
_loggerFactory, _loggerFactory,
options, options,
new ManagedFileSystem(_loggerFactory.CreateLogger<ManagedFileSystem>(), appPaths), new ManagedFileSystem(_loggerFactory.CreateLogger<ManagedFileSystem>(), appPaths),
GetImageEncoder(appPaths),
new NetworkManager(_loggerFactory.CreateLogger<NetworkManager>())); new NetworkManager(_loggerFactory.CreateLogger<NetworkManager>()));
try try
@ -553,25 +552,6 @@ namespace Jellyfin.Server
} }
} }
private static IImageEncoder GetImageEncoder(IApplicationPaths appPaths)
{
try
{
// Test if the native lib is available
SkiaEncoder.TestSkia();
return new SkiaEncoder(
_loggerFactory.CreateLogger<SkiaEncoder>(),
appPaths);
}
catch (Exception ex)
{
_logger.LogWarning(ex, $"Skia not available. Will fallback to {nameof(NullImageEncoder)}.");
}
return new NullImageEncoder();
}
private static void StartNewInstance(StartupOptions options) private static void StartNewInstance(StartupOptions options)
{ {
_logger.LogInformation("Starting new instance"); _logger.LogInformation("Starting new instance");