Merge pull request #2765 from mark-monteiro/register-services-correctly

Register And Construct Services Correctly Using DI Framework
pull/2961/head
Bond-009 5 years ago committed by GitHub
commit 07c4dfd8fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -8,7 +8,6 @@ using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller; using MediaBrowser.Controller;
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Drawing;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
@ -33,8 +32,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<ILibraryManager> _libraryManager; private readonly IMediaEncoder _mediaEncoder;
private readonly Func<IMediaEncoder> _mediaEncoder;
private bool _disposed = false; private bool _disposed = false;
@ -45,20 +43,17 @@ namespace Emby.Drawing
/// <param name="appPaths">The server application paths.</param> /// <param name="appPaths">The server application paths.</param>
/// <param name="fileSystem">The filesystem.</param> /// <param name="fileSystem">The filesystem.</param>
/// <param name="imageEncoder">The image encoder.</param> /// <param name="imageEncoder">The image encoder.</param>
/// <param name="libraryManager">The library manager.</param>
/// <param name="mediaEncoder">The media encoder.</param> /// <param name="mediaEncoder">The media encoder.</param>
public ImageProcessor( public ImageProcessor(
ILogger<ImageProcessor> logger, ILogger<ImageProcessor> logger,
IServerApplicationPaths appPaths, IServerApplicationPaths appPaths,
IFileSystem fileSystem, IFileSystem fileSystem,
IImageEncoder imageEncoder, IImageEncoder imageEncoder,
Func<ILibraryManager> libraryManager, IMediaEncoder mediaEncoder)
Func<IMediaEncoder> mediaEncoder)
{ {
_logger = logger; _logger = logger;
_fileSystem = fileSystem; _fileSystem = fileSystem;
_imageEncoder = imageEncoder; _imageEncoder = imageEncoder;
_libraryManager = libraryManager;
_mediaEncoder = mediaEncoder; _mediaEncoder = mediaEncoder;
_appPaths = appPaths; _appPaths = appPaths;
} }
@ -126,21 +121,9 @@ namespace Emby.Drawing
throw new ArgumentNullException(nameof(options)); throw new ArgumentNullException(nameof(options));
} }
var libraryManager = _libraryManager();
ItemImageInfo originalImage = options.Image; ItemImageInfo originalImage = options.Image;
BaseItem item = options.Item; BaseItem item = options.Item;
if (!originalImage.IsLocalFile)
{
if (item == null)
{
item = libraryManager.GetItemById(options.ItemId);
}
originalImage = await libraryManager.ConvertImageToLocal(item, originalImage, options.ImageIndex).ConfigureAwait(false);
}
string originalImagePath = originalImage.Path; string originalImagePath = originalImage.Path;
DateTime dateModified = originalImage.DateModified; DateTime dateModified = originalImage.DateModified;
ImageDimensions? originalImageSize = null; ImageDimensions? originalImageSize = null;
@ -312,10 +295,6 @@ namespace Emby.Drawing
/// <inheritdoc /> /// <inheritdoc />
public ImageDimensions GetImageDimensions(BaseItem item, ItemImageInfo info) public ImageDimensions GetImageDimensions(BaseItem item, ItemImageInfo info)
=> GetImageDimensions(item, info, true);
/// <inheritdoc />
public ImageDimensions GetImageDimensions(BaseItem item, ItemImageInfo info, bool updateItem)
{ {
int width = info.Width; int width = info.Width;
int height = info.Height; int height = info.Height;
@ -332,11 +311,6 @@ namespace Emby.Drawing
info.Width = size.Width; info.Width = size.Width;
info.Height = size.Height; info.Height = size.Height;
if (updateItem)
{
_libraryManager().UpdateImages(item);
}
return size; return size;
} }
@ -384,13 +358,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

@ -160,7 +160,7 @@ namespace Emby.Photos
try try
{ {
var size = _imageProcessor.GetImageDimensions(item, img, false); var size = _imageProcessor.GetImageDimensions(item, img);
if (size.Width > 0 && size.Height > 0) if (size.Width > 0 && size.Height > 0)
{ {

@ -86,7 +86,6 @@ using MediaBrowser.Model.Activity;
using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Cryptography; using MediaBrowser.Model.Cryptography;
using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.MediaInfo;
@ -104,7 +103,6 @@ using MediaBrowser.WebDashboard.Api;
using MediaBrowser.XbmcMetadata.Providers; using MediaBrowser.XbmcMetadata.Providers;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using OperatingSystem = MediaBrowser.Common.System.OperatingSystem; using OperatingSystem = MediaBrowser.Common.System.OperatingSystem;
@ -121,14 +119,20 @@ namespace Emby.Server.Implementations
/// </summary> /// </summary>
private static readonly string[] _relevantEnvVarPrefixes = { "JELLYFIN_", "DOTNET_", "ASPNETCORE_" }; private static readonly string[] _relevantEnvVarPrefixes = { "JELLYFIN_", "DOTNET_", "ASPNETCORE_" };
private SqliteUserRepository _userRepository; private readonly IFileSystem _fileSystemManager;
private SqliteDisplayPreferencesRepository _displayPreferencesRepository; private readonly INetworkManager _networkManager;
private readonly IXmlSerializer _xmlSerializer;
private readonly IStartupOptions _startupOptions;
private IMediaEncoder _mediaEncoder;
private ISessionManager _sessionManager;
private IHttpServer _httpServer;
private IHttpClient _httpClient;
/// <summary> /// <summary>
/// Gets a value indicating whether this instance can self restart. /// Gets a value indicating whether this instance can self restart.
/// </summary> /// </summary>
/// <value><c>true</c> if this instance can self restart; otherwise, <c>false</c>.</value> public bool CanSelfRestart => _startupOptions.RestartPath != null;
public abstract bool CanSelfRestart { get; }
public virtual bool CanLaunchWebBrowser public virtual bool CanLaunchWebBrowser
{ {
@ -139,7 +143,7 @@ namespace Emby.Server.Implementations
return false; return false;
} }
if (StartupOptions.IsService) if (_startupOptions.IsService)
{ {
return false; return false;
} }
@ -209,8 +213,6 @@ namespace Emby.Server.Implementations
/// <value>The configuration manager.</value> /// <value>The configuration manager.</value>
protected IConfigurationManager ConfigurationManager { get; set; } protected IConfigurationManager ConfigurationManager { get; set; }
public IFileSystem FileSystemManager { get; set; }
/// <summary> /// <summary>
/// Gets or sets the service provider. /// Gets or sets the service provider.
/// </summary> /// </summary>
@ -232,110 +234,6 @@ namespace Emby.Server.Implementations
/// <value>The server configuration manager.</value> /// <value>The server configuration manager.</value>
public IServerConfigurationManager ServerConfigurationManager => (IServerConfigurationManager)ConfigurationManager; public IServerConfigurationManager ServerConfigurationManager => (IServerConfigurationManager)ConfigurationManager;
/// <summary>
/// Gets or sets the user manager.
/// </summary>
/// <value>The user manager.</value>
public IUserManager UserManager { get; set; }
/// <summary>
/// Gets or sets the library manager.
/// </summary>
/// <value>The library manager.</value>
internal ILibraryManager LibraryManager { get; set; }
/// <summary>
/// Gets or sets the directory watchers.
/// </summary>
/// <value>The directory watchers.</value>
private ILibraryMonitor LibraryMonitor { get; set; }
/// <summary>
/// Gets or sets the provider manager.
/// </summary>
/// <value>The provider manager.</value>
private IProviderManager ProviderManager { get; set; }
/// <summary>
/// Gets or sets the HTTP server.
/// </summary>
/// <value>The HTTP server.</value>
private IHttpServer HttpServer { get; set; }
private IDtoService DtoService { get; set; }
public IImageProcessor ImageProcessor { get; set; }
/// <summary>
/// Gets or sets the media encoder.
/// </summary>
/// <value>The media encoder.</value>
private IMediaEncoder MediaEncoder { get; set; }
private ISubtitleEncoder SubtitleEncoder { get; set; }
private ISessionManager SessionManager { get; set; }
private ILiveTvManager LiveTvManager { get; set; }
public LocalizationManager LocalizationManager { get; set; }
private IEncodingManager EncodingManager { get; set; }
private IChannelManager ChannelManager { get; set; }
/// <summary>
/// Gets or sets the user data repository.
/// </summary>
/// <value>The user data repository.</value>
private IUserDataManager UserDataManager { get; set; }
internal SqliteItemRepository ItemRepository { get; set; }
private INotificationManager NotificationManager { get; set; }
private ISubtitleManager SubtitleManager { get; set; }
private IChapterManager ChapterManager { get; set; }
private IDeviceManager DeviceManager { get; set; }
internal IUserViewManager UserViewManager { get; set; }
private IAuthenticationRepository AuthenticationRepository { get; set; }
private ITVSeriesManager TVSeriesManager { get; set; }
private ICollectionManager CollectionManager { get; set; }
private IMediaSourceManager MediaSourceManager { get; set; }
/// <summary>
/// Gets the installation manager.
/// </summary>
/// <value>The installation manager.</value>
protected IInstallationManager InstallationManager { get; private set; }
protected IAuthService AuthService { get; private set; }
public IStartupOptions StartupOptions { get; }
internal IImageEncoder ImageEncoder { get; private set; }
protected readonly IXmlSerializer XmlSerializer;
protected ISocketFactory SocketFactory { get; private set; }
protected ITaskManager TaskManager { get; private set; }
public IHttpClient HttpClient { get; private set; }
protected INetworkManager NetworkManager { get; set; }
public IJsonSerializer JsonSerializer { get; private set; }
protected IIsoManager IsoManager { get; private set; }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ApplicationHost" /> class. /// Initializes a new instance of the <see cref="ApplicationHost" /> class.
/// </summary> /// </summary>
@ -344,29 +242,33 @@ 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();
NetworkManager = networkManager; _networkManager = networkManager;
networkManager.LocalSubnetsFn = GetConfiguredLocalSubnets; networkManager.LocalSubnetsFn = GetConfiguredLocalSubnets;
ApplicationPaths = applicationPaths; ApplicationPaths = applicationPaths;
LoggerFactory = loggerFactory; LoggerFactory = loggerFactory;
FileSystemManager = fileSystem; _fileSystemManager = fileSystem;
ConfigurationManager = new ServerConfigurationManager(ApplicationPaths, LoggerFactory, XmlSerializer, FileSystemManager); ConfigurationManager = new ServerConfigurationManager(ApplicationPaths, LoggerFactory, _xmlSerializer, _fileSystemManager);
Logger = LoggerFactory.CreateLogger("App"); Logger = LoggerFactory.CreateLogger<ApplicationHost>();
StartupOptions = options; _startupOptions = options;
ImageEncoder = imageEncoder;
fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem)); fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem));
NetworkManager.NetworkChanged += OnNetworkChanged; _networkManager.NetworkChanged += OnNetworkChanged;
CertificateInfo = new CertificateInfo
{
Path = ServerConfigurationManager.Configuration.CertificatePath,
Password = ServerConfigurationManager.Configuration.CertificatePassword
};
Certificate = GetCertificate(CertificateInfo);
} }
public string ExpandVirtualPath(string path) public string ExpandVirtualPath(string path)
@ -434,10 +336,7 @@ namespace Emby.Server.Implementations
} }
} }
/// <summary> /// <inheritdoc/>
/// Gets the name.
/// </summary>
/// <value>The name.</value>
public string Name => ApplicationProductName; public string Name => ApplicationProductName;
/// <summary> /// <summary>
@ -527,7 +426,7 @@ namespace Emby.Server.Implementations
ConfigurationManager.ConfigurationUpdated += OnConfigurationUpdated; ConfigurationManager.ConfigurationUpdated += OnConfigurationUpdated;
MediaEncoder.SetFFmpegPath(); _mediaEncoder.SetFFmpegPath();
Logger.LogInformation("ServerId: {0}", SystemId); Logger.LogInformation("ServerId: {0}", SystemId);
@ -539,7 +438,7 @@ namespace Emby.Server.Implementations
Logger.LogInformation("Executed all pre-startup entry points in {Elapsed:g}", stopWatch.Elapsed); Logger.LogInformation("Executed all pre-startup entry points in {Elapsed:g}", stopWatch.Elapsed);
Logger.LogInformation("Core startup complete"); Logger.LogInformation("Core startup complete");
HttpServer.GlobalResponse = null; _httpServer.GlobalResponse = null;
stopWatch.Restart(); stopWatch.Restart();
await Task.WhenAll(StartEntryPoints(entryPoints, false)).ConfigureAwait(false); await Task.WhenAll(StartEntryPoints(entryPoints, false)).ConfigureAwait(false);
@ -563,7 +462,7 @@ namespace Emby.Server.Implementations
} }
/// <inheritdoc/> /// <inheritdoc/>
public async Task InitAsync(IServiceCollection serviceCollection, IConfiguration startupConfig) public void Init(IServiceCollection serviceCollection)
{ {
HttpPort = ServerConfigurationManager.Configuration.HttpServerPortNumber; HttpPort = ServerConfigurationManager.Configuration.HttpServerPortNumber;
HttpsPort = ServerConfigurationManager.Configuration.HttpsPortNumber; HttpsPort = ServerConfigurationManager.Configuration.HttpsPortNumber;
@ -575,8 +474,6 @@ namespace Emby.Server.Implementations
HttpsPort = ServerConfiguration.DefaultHttpsPort; HttpsPort = ServerConfiguration.DefaultHttpsPort;
} }
JsonSerializer = new JsonSerializer();
if (Plugins != null) if (Plugins != null)
{ {
var pluginBuilder = new StringBuilder(); var pluginBuilder = new StringBuilder();
@ -596,7 +493,7 @@ namespace Emby.Server.Implementations
DiscoverTypes(); DiscoverTypes();
await RegisterServices(serviceCollection, startupConfig).ConfigureAwait(false); RegisterServices(serviceCollection);
} }
public async Task ExecuteWebsocketHandlerAsync(HttpContext context, Func<Task> next) public async Task ExecuteWebsocketHandlerAsync(HttpContext context, Func<Task> next)
@ -607,7 +504,7 @@ namespace Emby.Server.Implementations
return; return;
} }
await HttpServer.ProcessWebSocketRequest(context).ConfigureAwait(false); await _httpServer.ProcessWebSocketRequest(context).ConfigureAwait(false);
} }
public async Task ExecuteHttpHandlerAsync(HttpContext context, Func<Task> next) public async Task ExecuteHttpHandlerAsync(HttpContext context, Func<Task> next)
@ -623,14 +520,16 @@ namespace Emby.Server.Implementations
var localPath = context.Request.Path.ToString(); var localPath = context.Request.Path.ToString();
var req = new WebSocketSharpRequest(request, response, request.Path, LoggerFactory.CreateLogger<WebSocketSharpRequest>()); var req = new WebSocketSharpRequest(request, response, request.Path, LoggerFactory.CreateLogger<WebSocketSharpRequest>());
await HttpServer.RequestHandler(req, request.GetDisplayUrl(), request.Host.ToString(), localPath, context.RequestAborted).ConfigureAwait(false); await _httpServer.RequestHandler(req, request.GetDisplayUrl(), request.Host.ToString(), localPath, context.RequestAborted).ConfigureAwait(false);
} }
/// <summary> /// <summary>
/// Registers services/resources with the service collection that will be available via DI. /// Registers services/resources with the service collection that will be available via DI.
/// </summary> /// </summary>
protected async Task RegisterServices(IServiceCollection serviceCollection, IConfiguration startupConfig) protected virtual void RegisterServices(IServiceCollection serviceCollection)
{ {
serviceCollection.AddSingleton(_startupOptions);
serviceCollection.AddMemoryCache(); serviceCollection.AddMemoryCache();
serviceCollection.AddSingleton(ConfigurationManager); serviceCollection.AddSingleton(ConfigurationManager);
@ -638,240 +537,169 @@ namespace Emby.Server.Implementations
serviceCollection.AddSingleton<IApplicationPaths>(ApplicationPaths); serviceCollection.AddSingleton<IApplicationPaths>(ApplicationPaths);
serviceCollection.AddSingleton(JsonSerializer); serviceCollection.AddSingleton<IJsonSerializer, JsonSerializer>();
// TODO: Support for injecting ILogger should be deprecated in favour of ILogger<T> and this removed // TODO: Remove support for injecting ILogger completely
serviceCollection.AddSingleton<ILogger>(Logger); serviceCollection.AddSingleton((provider) =>
{
Logger.LogWarning("Injecting ILogger directly is deprecated and should be replaced with ILogger<T>");
return Logger;
});
serviceCollection.AddSingleton(FileSystemManager); serviceCollection.AddSingleton(_fileSystemManager);
serviceCollection.AddSingleton<TvdbClientManager>(); serviceCollection.AddSingleton<TvdbClientManager>();
HttpClient = new HttpClientManager.HttpClientManager( serviceCollection.AddSingleton<IHttpClient, HttpClientManager.HttpClientManager>();
ApplicationPaths,
LoggerFactory.CreateLogger<HttpClientManager.HttpClientManager>(),
FileSystemManager,
() => ApplicationUserAgent);
serviceCollection.AddSingleton(HttpClient);
serviceCollection.AddSingleton(NetworkManager); serviceCollection.AddSingleton(_networkManager);
IsoManager = new IsoManager(); serviceCollection.AddSingleton<IIsoManager, IsoManager>();
serviceCollection.AddSingleton(IsoManager);
TaskManager = new TaskManager(ApplicationPaths, JsonSerializer, LoggerFactory, FileSystemManager); serviceCollection.AddSingleton<ITaskManager, TaskManager>();
serviceCollection.AddSingleton(TaskManager);
serviceCollection.AddSingleton(XmlSerializer); serviceCollection.AddSingleton(_xmlSerializer);
serviceCollection.AddSingleton(typeof(IStreamHelper), typeof(StreamHelper)); serviceCollection.AddSingleton<IStreamHelper, StreamHelper>();
var cryptoProvider = new CryptographyProvider(); serviceCollection.AddSingleton<ICryptoProvider, CryptographyProvider>();
serviceCollection.AddSingleton<ICryptoProvider>(cryptoProvider);
SocketFactory = new SocketFactory(); serviceCollection.AddSingleton<ISocketFactory, SocketFactory>();
serviceCollection.AddSingleton(SocketFactory);
serviceCollection.AddSingleton(typeof(IInstallationManager), typeof(InstallationManager)); serviceCollection.AddSingleton<IInstallationManager, InstallationManager>();
serviceCollection.AddSingleton(typeof(IZipClient), typeof(ZipClient)); serviceCollection.AddSingleton<IZipClient, ZipClient>();
serviceCollection.AddSingleton(typeof(IHttpResultFactory), typeof(HttpResultFactory)); serviceCollection.AddSingleton<IHttpResultFactory, HttpResultFactory>();
serviceCollection.AddSingleton<IServerApplicationHost>(this); serviceCollection.AddSingleton<IServerApplicationHost>(this);
serviceCollection.AddSingleton<IServerApplicationPaths>(ApplicationPaths); serviceCollection.AddSingleton<IServerApplicationPaths>(ApplicationPaths);
serviceCollection.AddSingleton(ServerConfigurationManager); serviceCollection.AddSingleton(ServerConfigurationManager);
LocalizationManager = new LocalizationManager(ServerConfigurationManager, JsonSerializer, LoggerFactory.CreateLogger<LocalizationManager>()); serviceCollection.AddSingleton<ILocalizationManager, LocalizationManager>();
await LocalizationManager.LoadAll().ConfigureAwait(false);
serviceCollection.AddSingleton<ILocalizationManager>(LocalizationManager);
serviceCollection.AddSingleton<IBlurayExaminer>(new BdInfoExaminer(FileSystemManager));
UserDataManager = new UserDataManager(LoggerFactory, ServerConfigurationManager, () => UserManager); serviceCollection.AddSingleton<IBlurayExaminer, BdInfoExaminer>();
serviceCollection.AddSingleton(UserDataManager);
_displayPreferencesRepository = new SqliteDisplayPreferencesRepository( serviceCollection.AddSingleton<IUserDataRepository, SqliteUserDataRepository>();
LoggerFactory.CreateLogger<SqliteDisplayPreferencesRepository>(), serviceCollection.AddSingleton<IUserDataManager, UserDataManager>();
ApplicationPaths,
FileSystemManager);
serviceCollection.AddSingleton<IDisplayPreferencesRepository>(_displayPreferencesRepository);
ItemRepository = new SqliteItemRepository(ServerConfigurationManager, this, LoggerFactory.CreateLogger<SqliteItemRepository>(), LocalizationManager); serviceCollection.AddSingleton<IDisplayPreferencesRepository, SqliteDisplayPreferencesRepository>();
serviceCollection.AddSingleton<IItemRepository>(ItemRepository);
AuthenticationRepository = GetAuthenticationRepository(); serviceCollection.AddSingleton<IItemRepository, SqliteItemRepository>();
serviceCollection.AddSingleton(AuthenticationRepository);
_userRepository = GetUserRepository(); serviceCollection.AddSingleton<IAuthenticationRepository, AuthenticationRepository>();
UserManager = new UserManager( serviceCollection.AddSingleton<IUserRepository, SqliteUserRepository>();
LoggerFactory.CreateLogger<UserManager>(),
_userRepository,
XmlSerializer,
NetworkManager,
() => ImageProcessor,
() => DtoService,
this,
JsonSerializer,
FileSystemManager,
cryptoProvider);
serviceCollection.AddSingleton(UserManager); // TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required
serviceCollection.AddTransient(provider => new Lazy<IDtoService>(provider.GetRequiredService<IDtoService>));
serviceCollection.AddSingleton<IUserManager, UserManager>();
MediaEncoder = new MediaBrowser.MediaEncoding.Encoder.MediaEncoder( // TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required
LoggerFactory.CreateLogger<MediaBrowser.MediaEncoding.Encoder.MediaEncoder>(), // TODO: Add StartupOptions.FFmpegPath to IConfiguration and remove this custom activation
ServerConfigurationManager, serviceCollection.AddTransient(provider => new Lazy<EncodingHelper>(provider.GetRequiredService<EncodingHelper>));
FileSystemManager, serviceCollection.AddSingleton<IMediaEncoder>(provider =>
LocalizationManager, ActivatorUtilities.CreateInstance<MediaBrowser.MediaEncoding.Encoder.MediaEncoder>(provider, _startupOptions.FFmpegPath ?? string.Empty));
() => SubtitleEncoder,
startupConfig,
StartupOptions.FFmpegPath);
serviceCollection.AddSingleton(MediaEncoder);
LibraryManager = new LibraryManager(this, LoggerFactory, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager, () => UserViewManager, MediaEncoder); // TODO: Refactor to eliminate the circular dependencies here so that Lazy<T> isn't required
serviceCollection.AddSingleton(LibraryManager); serviceCollection.AddTransient(provider => new Lazy<ILibraryMonitor>(provider.GetRequiredService<ILibraryMonitor>));
serviceCollection.AddTransient(provider => new Lazy<IProviderManager>(provider.GetRequiredService<IProviderManager>));
serviceCollection.AddTransient(provider => new Lazy<IUserViewManager>(provider.GetRequiredService<IUserViewManager>));
serviceCollection.AddSingleton<ILibraryManager, LibraryManager>();
var musicManager = new MusicManager(LibraryManager); serviceCollection.AddSingleton<IMusicManager, MusicManager>();
serviceCollection.AddSingleton<IMusicManager>(musicManager);
LibraryMonitor = new LibraryMonitor(LoggerFactory, LibraryManager, ServerConfigurationManager, FileSystemManager); serviceCollection.AddSingleton<ILibraryMonitor, LibraryMonitor>();
serviceCollection.AddSingleton(LibraryMonitor);
serviceCollection.AddSingleton<ISearchEngine>(new SearchEngine(LoggerFactory, LibraryManager, UserManager)); serviceCollection.AddSingleton<ISearchEngine, SearchEngine>();
CertificateInfo = GetCertificateInfo(true);
Certificate = GetCertificate(CertificateInfo);
serviceCollection.AddSingleton<ServiceController>(); serviceCollection.AddSingleton<ServiceController>();
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, () => LibraryManager, () => MediaEncoder); serviceCollection.AddSingleton<IImageProcessor, ImageProcessor>();
serviceCollection.AddSingleton(ImageProcessor);
TVSeriesManager = new TVSeriesManager(UserManager, UserDataManager, LibraryManager, ServerConfigurationManager);
serviceCollection.AddSingleton(TVSeriesManager);
DeviceManager = new DeviceManager(AuthenticationRepository, JsonSerializer, LibraryManager, LocalizationManager, UserManager, FileSystemManager, LibraryMonitor, ServerConfigurationManager);
serviceCollection.AddSingleton(DeviceManager);
MediaSourceManager = new MediaSourceManager(ItemRepository, ApplicationPaths, LocalizationManager, UserManager, LibraryManager, LoggerFactory, JsonSerializer, FileSystemManager, UserDataManager, () => MediaEncoder);
serviceCollection.AddSingleton(MediaSourceManager);
SubtitleManager = new SubtitleManager(LoggerFactory, FileSystemManager, LibraryMonitor, MediaSourceManager, LocalizationManager);
serviceCollection.AddSingleton(SubtitleManager);
ProviderManager = new ProviderManager(HttpClient, SubtitleManager, ServerConfigurationManager, LibraryMonitor, LoggerFactory, FileSystemManager, ApplicationPaths, () => LibraryManager, JsonSerializer);
serviceCollection.AddSingleton(ProviderManager);
DtoService = new DtoService(LoggerFactory, LibraryManager, UserDataManager, ItemRepository, ImageProcessor, ProviderManager, this, () => MediaSourceManager, () => LiveTvManager);
serviceCollection.AddSingleton(DtoService);
ChannelManager = new ChannelManager(
UserManager,
DtoService,
LibraryManager,
LoggerFactory.CreateLogger<ChannelManager>(),
ServerConfigurationManager,
FileSystemManager,
UserDataManager,
JsonSerializer,
ProviderManager);
serviceCollection.AddSingleton(ChannelManager);
SessionManager = new SessionManager(
LoggerFactory.CreateLogger<SessionManager>(),
UserDataManager,
LibraryManager,
UserManager,
musicManager,
DtoService,
ImageProcessor,
this,
AuthenticationRepository,
DeviceManager,
MediaSourceManager);
serviceCollection.AddSingleton(SessionManager);
serviceCollection.AddSingleton<IDlnaManager>(
new DlnaManager(XmlSerializer, FileSystemManager, ApplicationPaths, LoggerFactory, JsonSerializer, this));
CollectionManager = new CollectionManager(LibraryManager, ApplicationPaths, LocalizationManager, FileSystemManager, LibraryMonitor, LoggerFactory, ProviderManager);
serviceCollection.AddSingleton(CollectionManager);
serviceCollection.AddSingleton(typeof(IPlaylistManager), typeof(PlaylistManager));
LiveTvManager = new LiveTvManager(this, ServerConfigurationManager, LoggerFactory, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager, LocalizationManager, JsonSerializer, FileSystemManager, () => ChannelManager);
serviceCollection.AddSingleton(LiveTvManager);
UserViewManager = new UserViewManager(LibraryManager, LocalizationManager, UserManager, ChannelManager, LiveTvManager, ServerConfigurationManager);
serviceCollection.AddSingleton(UserViewManager);
NotificationManager = new NotificationManager(
LoggerFactory.CreateLogger<NotificationManager>(),
UserManager,
ServerConfigurationManager);
serviceCollection.AddSingleton(NotificationManager);
serviceCollection.AddSingleton<IDeviceDiscovery>(new DeviceDiscovery(ServerConfigurationManager));
ChapterManager = new ChapterManager(ItemRepository);
serviceCollection.AddSingleton(ChapterManager);
EncodingManager = new MediaEncoder.EncodingManager(
LoggerFactory.CreateLogger<MediaEncoder.EncodingManager>(),
FileSystemManager,
MediaEncoder,
ChapterManager,
LibraryManager);
serviceCollection.AddSingleton(EncodingManager);
var activityLogRepo = GetActivityLogRepository();
serviceCollection.AddSingleton(activityLogRepo);
serviceCollection.AddSingleton<IActivityManager>(new ActivityManager(activityLogRepo, UserManager));
var authContext = new AuthorizationContext(AuthenticationRepository, UserManager);
serviceCollection.AddSingleton<IAuthorizationContext>(authContext);
serviceCollection.AddSingleton<ISessionContext>(new SessionContext(UserManager, authContext, SessionManager));
AuthService = new AuthService(LoggerFactory.CreateLogger<AuthService>(), authContext, ServerConfigurationManager, SessionManager, NetworkManager);
serviceCollection.AddSingleton(AuthService);
SubtitleEncoder = new MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder(
LibraryManager,
LoggerFactory.CreateLogger<MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder>(),
ApplicationPaths,
FileSystemManager,
MediaEncoder,
HttpClient,
MediaSourceManager);
serviceCollection.AddSingleton(SubtitleEncoder);
serviceCollection.AddSingleton(typeof(IResourceFileManager), typeof(ResourceFileManager));
serviceCollection.AddSingleton<EncodingHelper>();
serviceCollection.AddSingleton(typeof(IAttachmentExtractor), typeof(MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor)); serviceCollection.AddSingleton<ITVSeriesManager, TVSeriesManager>();
_displayPreferencesRepository.Initialize(); serviceCollection.AddSingleton<IDeviceManager, DeviceManager>();
var userDataRepo = new SqliteUserDataRepository(LoggerFactory.CreateLogger<SqliteUserDataRepository>(), ApplicationPaths); serviceCollection.AddSingleton<IMediaSourceManager, MediaSourceManager>();
SetStaticProperties(); serviceCollection.AddSingleton<ISubtitleManager, SubtitleManager>();
serviceCollection.AddSingleton<IProviderManager, ProviderManager>();
// TODO: Refactor to eliminate the circular dependency here so that Lazy<T> isn't required
serviceCollection.AddTransient(provider => new Lazy<ILiveTvManager>(provider.GetRequiredService<ILiveTvManager>));
serviceCollection.AddSingleton<IDtoService, DtoService>();
serviceCollection.AddSingleton<IChannelManager, ChannelManager>();
serviceCollection.AddSingleton<ISessionManager, SessionManager>();
serviceCollection.AddSingleton<IDlnaManager, DlnaManager>();
serviceCollection.AddSingleton<ICollectionManager, CollectionManager>();
((UserManager)UserManager).Initialize(); serviceCollection.AddSingleton<IPlaylistManager, PlaylistManager>();
((UserDataManager)UserDataManager).Repository = userDataRepo; serviceCollection.AddSingleton<LiveTvDtoService>();
ItemRepository.Initialize(userDataRepo, UserManager); serviceCollection.AddSingleton<ILiveTvManager, LiveTvManager>();
((LibraryManager)LibraryManager).ItemRepository = ItemRepository;
serviceCollection.AddSingleton<IUserViewManager, UserViewManager>();
serviceCollection.AddSingleton<INotificationManager, NotificationManager>();
serviceCollection.AddSingleton<IDeviceDiscovery, DeviceDiscovery>();
serviceCollection.AddSingleton<IChapterManager, ChapterManager>();
serviceCollection.AddSingleton<IEncodingManager, MediaEncoder.EncodingManager>();
serviceCollection.AddSingleton<IActivityRepository, ActivityRepository>();
serviceCollection.AddSingleton<IActivityManager, ActivityManager>();
serviceCollection.AddSingleton<IAuthorizationContext, AuthorizationContext>();
serviceCollection.AddSingleton<ISessionContext, SessionContext>();
serviceCollection.AddSingleton<IAuthService, AuthService>();
serviceCollection.AddSingleton<ISubtitleEncoder, MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder>();
serviceCollection.AddSingleton<IResourceFileManager, ResourceFileManager>();
serviceCollection.AddSingleton<EncodingHelper>();
serviceCollection.AddSingleton<IAttachmentExtractor, MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor>();
} }
/// <summary> /// <summary>
/// Create services registered with the service container that need to be initialized at application startup. /// Create services registered with the service container that need to be initialized at application startup.
/// </summary> /// </summary>
public void InitializeServices() /// <returns>A task representing the service initialization operation.</returns>
public async Task InitializeServices()
{ {
HttpServer = Resolve<IHttpServer>(); var localizationManager = (LocalizationManager)Resolve<ILocalizationManager>();
await localizationManager.LoadAll().ConfigureAwait(false);
_mediaEncoder = Resolve<IMediaEncoder>();
_sessionManager = Resolve<ISessionManager>();
_httpServer = Resolve<IHttpServer>();
_httpClient = Resolve<IHttpClient>();
((SqliteDisplayPreferencesRepository)Resolve<IDisplayPreferencesRepository>()).Initialize();
((AuthenticationRepository)Resolve<IAuthenticationRepository>()).Initialize();
((SqliteUserRepository)Resolve<IUserRepository>()).Initialize();
((ActivityRepository)Resolve<IActivityRepository>()).Initialize();
SetStaticProperties();
var userManager = (UserManager)Resolve<IUserManager>();
userManager.Initialize();
var userDataRepo = (SqliteUserDataRepository)Resolve<IUserDataRepository>();
((SqliteItemRepository)Resolve<IItemRepository>()).Initialize(userDataRepo, userManager);
FindParts();
} }
public static void LogEnvironmentInfo(ILogger logger, IApplicationPaths appPaths) public static void LogEnvironmentInfo(ILogger logger, IApplicationPaths appPaths)
@ -940,75 +768,38 @@ namespace Emby.Server.Implementations
} }
} }
/// <summary>
/// Gets the user repository.
/// </summary>
/// <returns><see cref="Task{SqliteUserRepository}" />.</returns>
private SqliteUserRepository GetUserRepository()
{
var repo = new SqliteUserRepository(
LoggerFactory.CreateLogger<SqliteUserRepository>(),
ApplicationPaths);
repo.Initialize();
return repo;
}
private IAuthenticationRepository GetAuthenticationRepository()
{
var repo = new AuthenticationRepository(LoggerFactory, ServerConfigurationManager);
repo.Initialize();
return repo;
}
private IActivityRepository GetActivityLogRepository()
{
var repo = new ActivityRepository(LoggerFactory.CreateLogger<ActivityRepository>(), ServerConfigurationManager.ApplicationPaths, FileSystemManager);
repo.Initialize();
return repo;
}
/// <summary> /// <summary>
/// Dirty hacks. /// Dirty hacks.
/// </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 = Resolve<ILogger<BaseItem>>();
BaseItem.ConfigurationManager = ServerConfigurationManager; BaseItem.ConfigurationManager = ServerConfigurationManager;
BaseItem.LibraryManager = LibraryManager; BaseItem.LibraryManager = Resolve<ILibraryManager>();
BaseItem.ProviderManager = ProviderManager; BaseItem.ProviderManager = Resolve<IProviderManager>();
BaseItem.LocalizationManager = LocalizationManager; BaseItem.LocalizationManager = Resolve<ILocalizationManager>();
BaseItem.ItemRepository = ItemRepository; BaseItem.ItemRepository = Resolve<IItemRepository>();
User.UserManager = UserManager; User.UserManager = Resolve<IUserManager>();
BaseItem.FileSystem = FileSystemManager; BaseItem.FileSystem = _fileSystemManager;
BaseItem.UserDataManager = UserDataManager; BaseItem.UserDataManager = Resolve<IUserDataManager>();
BaseItem.ChannelManager = ChannelManager; BaseItem.ChannelManager = Resolve<IChannelManager>();
Video.LiveTvManager = LiveTvManager; Video.LiveTvManager = Resolve<ILiveTvManager>();
Folder.UserViewManager = UserViewManager; Folder.UserViewManager = Resolve<IUserViewManager>();
UserView.TVSeriesManager = TVSeriesManager; UserView.TVSeriesManager = Resolve<ITVSeriesManager>();
UserView.CollectionManager = CollectionManager; UserView.CollectionManager = Resolve<ICollectionManager>();
BaseItem.MediaSourceManager = MediaSourceManager; BaseItem.MediaSourceManager = Resolve<IMediaSourceManager>();
CollectionFolder.XmlSerializer = XmlSerializer; CollectionFolder.XmlSerializer = _xmlSerializer;
CollectionFolder.JsonSerializer = JsonSerializer; CollectionFolder.JsonSerializer = Resolve<IJsonSerializer>();
CollectionFolder.ApplicationHost = this; CollectionFolder.ApplicationHost = this;
AuthenticatedAttribute.AuthService = AuthService; AuthenticatedAttribute.AuthService = Resolve<IAuthService>();
} }
/// <summary> /// <summary>
/// Finds the parts. /// Finds plugin components and register them with the appropriate services.
/// </summary> /// </summary>
public void FindParts() private void FindParts()
{ {
InstallationManager = ServiceProvider.GetService<IInstallationManager>();
if (!ServerConfigurationManager.Configuration.IsPortAuthorized) if (!ServerConfigurationManager.Configuration.IsPortAuthorized)
{ {
ServerConfigurationManager.Configuration.IsPortAuthorized = true; ServerConfigurationManager.Configuration.IsPortAuthorized = true;
@ -1021,34 +812,34 @@ namespace Emby.Server.Implementations
.Where(i => i != null) .Where(i => i != null)
.ToArray(); .ToArray();
HttpServer.Init(GetExportTypes<IService>(), GetExports<IWebSocketListener>(), GetUrlPrefixes()); _httpServer.Init(GetExportTypes<IService>(), GetExports<IWebSocketListener>(), GetUrlPrefixes());
LibraryManager.AddParts( Resolve<ILibraryManager>().AddParts(
GetExports<IResolverIgnoreRule>(), GetExports<IResolverIgnoreRule>(),
GetExports<IItemResolver>(), GetExports<IItemResolver>(),
GetExports<IIntroProvider>(), GetExports<IIntroProvider>(),
GetExports<IBaseItemComparer>(), GetExports<IBaseItemComparer>(),
GetExports<ILibraryPostScanTask>()); GetExports<ILibraryPostScanTask>());
ProviderManager.AddParts( Resolve<IProviderManager>().AddParts(
GetExports<IImageProvider>(), GetExports<IImageProvider>(),
GetExports<IMetadataService>(), GetExports<IMetadataService>(),
GetExports<IMetadataProvider>(), GetExports<IMetadataProvider>(),
GetExports<IMetadataSaver>(), GetExports<IMetadataSaver>(),
GetExports<IExternalId>()); GetExports<IExternalId>());
LiveTvManager.AddParts(GetExports<ILiveTvService>(), GetExports<ITunerHost>(), GetExports<IListingsProvider>()); Resolve<ILiveTvManager>().AddParts(GetExports<ILiveTvService>(), GetExports<ITunerHost>(), GetExports<IListingsProvider>());
SubtitleManager.AddParts(GetExports<ISubtitleProvider>()); Resolve<ISubtitleManager>().AddParts(GetExports<ISubtitleProvider>());
ChannelManager.AddParts(GetExports<IChannel>()); Resolve<IChannelManager>().AddParts(GetExports<IChannel>());
MediaSourceManager.AddParts(GetExports<IMediaSourceProvider>()); Resolve<IMediaSourceManager>().AddParts(GetExports<IMediaSourceProvider>());
NotificationManager.AddParts(GetExports<INotificationService>(), GetExports<INotificationTypeFactory>()); Resolve<INotificationManager>().AddParts(GetExports<INotificationService>(), GetExports<INotificationTypeFactory>());
UserManager.AddParts(GetExports<IAuthenticationProvider>(), GetExports<IPasswordResetProvider>()); Resolve<IUserManager>().AddParts(GetExports<IAuthenticationProvider>(), GetExports<IPasswordResetProvider>());
IsoManager.AddParts(GetExports<IIsoMounter>()); Resolve<IIsoManager>().AddParts(GetExports<IIsoMounter>());
} }
private IPlugin LoadPlugin(IPlugin plugin) private IPlugin LoadPlugin(IPlugin plugin)
@ -1155,16 +946,6 @@ namespace Emby.Server.Implementations
}); });
} }
private CertificateInfo GetCertificateInfo(bool generateCertificate)
{
// Custom cert
return new CertificateInfo
{
Path = ServerConfigurationManager.Configuration.CertificatePath,
Password = ServerConfigurationManager.Configuration.CertificatePassword
};
}
/// <summary> /// <summary>
/// Called when [configuration updated]. /// Called when [configuration updated].
/// </summary> /// </summary>
@ -1191,14 +972,13 @@ namespace Emby.Server.Implementations
} }
} }
if (!HttpServer.UrlPrefixes.SequenceEqual(GetUrlPrefixes(), StringComparer.OrdinalIgnoreCase)) if (!_httpServer.UrlPrefixes.SequenceEqual(GetUrlPrefixes(), StringComparer.OrdinalIgnoreCase))
{ {
requiresRestart = true; requiresRestart = true;
} }
var currentCertPath = CertificateInfo?.Path; var currentCertPath = CertificateInfo?.Path;
var newCertInfo = GetCertificateInfo(false); var newCertPath = ServerConfigurationManager.Configuration.CertificatePath;
var newCertPath = newCertInfo?.Path;
if (!string.Equals(currentCertPath, newCertPath, StringComparison.OrdinalIgnoreCase)) if (!string.Equals(currentCertPath, newCertPath, StringComparison.OrdinalIgnoreCase))
{ {
@ -1251,7 +1031,7 @@ namespace Emby.Server.Implementations
{ {
try try
{ {
await SessionManager.SendServerRestartNotification(CancellationToken.None).ConfigureAwait(false); await _sessionManager.SendServerRestartNotification(CancellationToken.None).ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -1355,7 +1135,7 @@ namespace Emby.Server.Implementations
IsShuttingDown = IsShuttingDown, IsShuttingDown = IsShuttingDown,
Version = ApplicationVersionString, Version = ApplicationVersionString,
WebSocketPortNumber = HttpPort, WebSocketPortNumber = HttpPort,
CompletedInstallations = InstallationManager.CompletedInstallations.ToArray(), CompletedInstallations = Resolve<IInstallationManager>().CompletedInstallations.ToArray(),
Id = SystemId, Id = SystemId,
ProgramDataPath = ApplicationPaths.ProgramDataPath, ProgramDataPath = ApplicationPaths.ProgramDataPath,
WebPath = ApplicationPaths.WebPath, WebPath = ApplicationPaths.WebPath,
@ -1375,14 +1155,14 @@ namespace Emby.Server.Implementations
ServerName = FriendlyName, ServerName = FriendlyName,
LocalAddress = localAddress, LocalAddress = localAddress,
SupportsLibraryMonitor = true, SupportsLibraryMonitor = true,
EncoderLocation = MediaEncoder.EncoderLocation, EncoderLocation = _mediaEncoder.EncoderLocation,
SystemArchitecture = RuntimeInformation.OSArchitecture, SystemArchitecture = RuntimeInformation.OSArchitecture,
PackageName = StartupOptions.PackageName PackageName = _startupOptions.PackageName
}; };
} }
public IEnumerable<WakeOnLanInfo> GetWakeOnLanInfo() public IEnumerable<WakeOnLanInfo> GetWakeOnLanInfo()
=> NetworkManager.GetMacAddresses() => _networkManager.GetMacAddresses()
.Select(i => new WakeOnLanInfo(i)) .Select(i => new WakeOnLanInfo(i))
.ToList(); .ToList();
@ -1494,7 +1274,7 @@ namespace Emby.Server.Implementations
if (addresses.Count == 0) if (addresses.Count == 0)
{ {
addresses.AddRange(NetworkManager.GetLocalIpAddresses(ServerConfigurationManager.Configuration.IgnoreVirtualInterfaces)); addresses.AddRange(_networkManager.GetLocalIpAddresses(ServerConfigurationManager.Configuration.IgnoreVirtualInterfaces));
} }
var resultList = new List<IPAddress>(); var resultList = new List<IPAddress>();
@ -1561,7 +1341,7 @@ namespace Emby.Server.Implementations
try try
{ {
using (var response = await HttpClient.SendAsync( using (var response = await _httpClient.SendAsync(
new HttpRequestOptions new HttpRequestOptions
{ {
Url = apiUrl, Url = apiUrl,
@ -1614,7 +1394,7 @@ namespace Emby.Server.Implementations
try try
{ {
await SessionManager.SendServerShutdownNotification(CancellationToken.None).ConfigureAwait(false); await _sessionManager.SendServerShutdownNotification(CancellationToken.None).ConfigureAwait(false);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -1735,14 +1515,8 @@ namespace Emby.Server.Implementations
Logger.LogError(ex, "Error disposing {Type}", part.GetType().Name); Logger.LogError(ex, "Error disposing {Type}", part.GetType().Name);
} }
} }
_userRepository?.Dispose();
_displayPreferencesRepository?.Dispose();
} }
_userRepository = null;
_displayPreferencesRepository = null;
_disposed = true; _disposed = true;
} }
} }

@ -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. GetImageCacheTag() is the only method used and it can be converted to a static helper method
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);
} }
} }

@ -38,10 +38,11 @@ namespace Emby.Server.Implementations.Devices
private readonly IServerConfigurationManager _config; private readonly IServerConfigurationManager _config;
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly ILocalizationManager _localizationManager; private readonly ILocalizationManager _localizationManager;
private readonly IAuthenticationRepository _authRepo; private readonly IAuthenticationRepository _authRepo;
private readonly Dictionary<string, ClientCapabilities> _capabilitiesCache;
public event EventHandler<GenericEventArgs<Tuple<string, DeviceOptions>>> DeviceOptionsUpdated; public event EventHandler<GenericEventArgs<Tuple<string, DeviceOptions>>> DeviceOptionsUpdated;
public event EventHandler<GenericEventArgs<CameraImageUploadInfo>> CameraImageUploaded; public event EventHandler<GenericEventArgs<CameraImageUploadInfo>> CameraImageUploaded;
private readonly object _cameraUploadSyncLock = new object(); private readonly object _cameraUploadSyncLock = new object();
@ -65,10 +66,9 @@ namespace Emby.Server.Implementations.Devices
_libraryManager = libraryManager; _libraryManager = libraryManager;
_localizationManager = localizationManager; _localizationManager = localizationManager;
_authRepo = authRepo; _authRepo = authRepo;
_capabilitiesCache = new Dictionary<string, ClientCapabilities>(StringComparer.OrdinalIgnoreCase);
} }
private Dictionary<string, ClientCapabilities> _capabilitiesCache = new Dictionary<string, ClientCapabilities>(StringComparer.OrdinalIgnoreCase);
public void SaveCapabilities(string deviceId, ClientCapabilities capabilities) public void SaveCapabilities(string deviceId, ClientCapabilities capabilities)
{ {
var path = Path.Combine(GetDevicePath(deviceId), "capabilities.json"); var path = Path.Combine(GetDevicePath(deviceId), "capabilities.json");

@ -38,21 +38,23 @@ namespace Emby.Server.Implementations.Dto
private readonly IProviderManager _providerManager; private readonly IProviderManager _providerManager;
private readonly IApplicationHost _appHost; private readonly IApplicationHost _appHost;
private readonly Func<IMediaSourceManager> _mediaSourceManager; private readonly IMediaSourceManager _mediaSourceManager;
private readonly Func<ILiveTvManager> _livetvManager; private readonly Lazy<ILiveTvManager> _livetvManagerFactory;
private ILiveTvManager LivetvManager => _livetvManagerFactory.Value;
public DtoService( public DtoService(
ILoggerFactory loggerFactory, ILogger<DtoService> logger,
ILibraryManager libraryManager, ILibraryManager libraryManager,
IUserDataManager userDataRepository, IUserDataManager userDataRepository,
IItemRepository itemRepo, IItemRepository itemRepo,
IImageProcessor imageProcessor, IImageProcessor imageProcessor,
IProviderManager providerManager, IProviderManager providerManager,
IApplicationHost appHost, IApplicationHost appHost,
Func<IMediaSourceManager> mediaSourceManager, IMediaSourceManager mediaSourceManager,
Func<ILiveTvManager> livetvManager) Lazy<ILiveTvManager> livetvManagerFactory)
{ {
_logger = loggerFactory.CreateLogger(nameof(DtoService)); _logger = logger;
_libraryManager = libraryManager; _libraryManager = libraryManager;
_userDataRepository = userDataRepository; _userDataRepository = userDataRepository;
_itemRepo = itemRepo; _itemRepo = itemRepo;
@ -60,7 +62,7 @@ namespace Emby.Server.Implementations.Dto
_providerManager = providerManager; _providerManager = providerManager;
_appHost = appHost; _appHost = appHost;
_mediaSourceManager = mediaSourceManager; _mediaSourceManager = mediaSourceManager;
_livetvManager = livetvManager; _livetvManagerFactory = livetvManagerFactory;
} }
/// <summary> /// <summary>
@ -125,12 +127,12 @@ namespace Emby.Server.Implementations.Dto
if (programTuples.Count > 0) if (programTuples.Count > 0)
{ {
_livetvManager().AddInfoToProgramDto(programTuples, options.Fields, user).GetAwaiter().GetResult(); LivetvManager.AddInfoToProgramDto(programTuples, options.Fields, user).GetAwaiter().GetResult();
} }
if (channelTuples.Count > 0) if (channelTuples.Count > 0)
{ {
_livetvManager().AddChannelInfo(channelTuples, options, user); LivetvManager.AddChannelInfo(channelTuples, options, user);
} }
return returnItems; return returnItems;
@ -142,12 +144,12 @@ namespace Emby.Server.Implementations.Dto
if (item is LiveTvChannel tvChannel) if (item is LiveTvChannel tvChannel)
{ {
var list = new List<(BaseItemDto, LiveTvChannel)>(1) { (dto, tvChannel) }; var list = new List<(BaseItemDto, LiveTvChannel)>(1) { (dto, tvChannel) };
_livetvManager().AddChannelInfo(list, options, user); LivetvManager.AddChannelInfo(list, options, user);
} }
else if (item is LiveTvProgram) else if (item is LiveTvProgram)
{ {
var list = new List<(BaseItem, BaseItemDto)>(1) { (item, dto) }; var list = new List<(BaseItem, BaseItemDto)>(1) { (item, dto) };
var task = _livetvManager().AddInfoToProgramDto(list, options.Fields, user); var task = LivetvManager.AddInfoToProgramDto(list, options.Fields, user);
Task.WaitAll(task); Task.WaitAll(task);
} }
@ -223,7 +225,7 @@ namespace Emby.Server.Implementations.Dto
if (item is IHasMediaSources if (item is IHasMediaSources
&& options.ContainsField(ItemFields.MediaSources)) && options.ContainsField(ItemFields.MediaSources))
{ {
dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(item, true, user).ToArray(); dto.MediaSources = _mediaSourceManager.GetStaticMediaSources(item, true, user).ToArray();
NormalizeMediaSourceContainers(dto); NormalizeMediaSourceContainers(dto);
} }
@ -254,7 +256,7 @@ namespace Emby.Server.Implementations.Dto
dto.Etag = item.GetEtag(user); dto.Etag = item.GetEtag(user);
} }
var liveTvManager = _livetvManager(); var liveTvManager = LivetvManager;
var activeRecording = liveTvManager.GetActiveRecordingInfo(item.Path); var activeRecording = liveTvManager.GetActiveRecordingInfo(item.Path);
if (activeRecording != null) if (activeRecording != null)
{ {
@ -1045,7 +1047,7 @@ namespace Emby.Server.Implementations.Dto
} }
else else
{ {
mediaStreams = _mediaSourceManager().GetStaticMediaSources(item, true)[0].MediaStreams.ToArray(); mediaStreams = _mediaSourceManager.GetStaticMediaSources(item, true)[0].MediaStreams.ToArray();
} }
dto.MediaStreams = mediaStreams; dto.MediaStreams = mediaStreams;

@ -16,17 +16,25 @@ namespace Emby.Server.Implementations.EntryPoints
private readonly IServerApplicationHost _appHost; private readonly IServerApplicationHost _appHost;
private readonly IConfiguration _appConfig; private readonly IConfiguration _appConfig;
private readonly IServerConfigurationManager _config; private readonly IServerConfigurationManager _config;
private readonly IStartupOptions _startupOptions;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="StartupWizard"/> class. /// Initializes a new instance of the <see cref="StartupWizard"/> class.
/// </summary> /// </summary>
/// <param name="appHost">The application host.</param> /// <param name="appHost">The application host.</param>
/// <param name="appConfig">The application configuration.</param>
/// <param name="config">The configuration manager.</param> /// <param name="config">The configuration manager.</param>
public StartupWizard(IServerApplicationHost appHost, IConfiguration appConfig, IServerConfigurationManager config) /// <param name="startupOptions">The application startup options.</param>
public StartupWizard(
IServerApplicationHost appHost,
IConfiguration appConfig,
IServerConfigurationManager config,
IStartupOptions startupOptions)
{ {
_appHost = appHost; _appHost = appHost;
_appConfig = appConfig; _appConfig = appConfig;
_config = config; _config = config;
_startupOptions = startupOptions;
} }
/// <inheritdoc /> /// <inheritdoc />
@ -51,8 +59,7 @@ namespace Emby.Server.Implementations.EntryPoints
} }
// Do nothing if the web app is configured to not run automatically // Do nothing if the web app is configured to not run automatically
var options = ((ApplicationHost)_appHost).StartupOptions; if (!_config.Configuration.AutoRunWebApp || _startupOptions.NoAutoRunWebApp)
if (!_config.Configuration.AutoRunWebApp || options.NoAutoRunWebApp)
{ {
return; return;
} }

@ -6,6 +6,7 @@ using System.Linq;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Common;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net; using MediaBrowser.Common.Net;
@ -24,7 +25,7 @@ namespace Emby.Server.Implementations.HttpClientManager
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IApplicationPaths _appPaths; private readonly IApplicationPaths _appPaths;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly Func<string> _defaultUserAgentFn; private readonly IApplicationHost _appHost;
/// <summary> /// <summary>
/// Holds a dictionary of http clients by host. Use GetHttpClient(host) to retrieve or create a client for web requests. /// Holds a dictionary of http clients by host. Use GetHttpClient(host) to retrieve or create a client for web requests.
@ -40,12 +41,12 @@ namespace Emby.Server.Implementations.HttpClientManager
IApplicationPaths appPaths, IApplicationPaths appPaths,
ILogger<HttpClientManager> logger, ILogger<HttpClientManager> logger,
IFileSystem fileSystem, IFileSystem fileSystem,
Func<string> defaultUserAgentFn) IApplicationHost appHost)
{ {
_logger = logger ?? throw new ArgumentNullException(nameof(logger)); _logger = logger ?? throw new ArgumentNullException(nameof(logger));
_fileSystem = fileSystem; _fileSystem = fileSystem;
_appPaths = appPaths ?? throw new ArgumentNullException(nameof(appPaths)); _appPaths = appPaths ?? throw new ArgumentNullException(nameof(appPaths));
_defaultUserAgentFn = defaultUserAgentFn; _appHost = appHost;
} }
/// <summary> /// <summary>
@ -91,7 +92,7 @@ namespace Emby.Server.Implementations.HttpClientManager
if (options.EnableDefaultUserAgent if (options.EnableDefaultUserAgent
&& !request.Headers.TryGetValues(HeaderNames.UserAgent, out _)) && !request.Headers.TryGetValues(HeaderNames.UserAgent, out _))
{ {
request.Headers.Add(HeaderNames.UserAgent, _defaultUserAgentFn()); request.Headers.Add(HeaderNames.UserAgent, _appHost.ApplicationUserAgent);
} }
switch (options.DecompressionMethod) switch (options.DecompressionMethod)

@ -17,6 +17,11 @@ namespace Emby.Server.Implementations.IO
{ {
public class LibraryMonitor : ILibraryMonitor public class LibraryMonitor : ILibraryMonitor
{ {
private readonly ILogger _logger;
private readonly ILibraryManager _libraryManager;
private readonly IServerConfigurationManager _configurationManager;
private readonly IFileSystem _fileSystem;
/// <summary> /// <summary>
/// The file system watchers. /// The file system watchers.
/// </summary> /// </summary>
@ -113,34 +118,23 @@ namespace Emby.Server.Implementations.IO
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.LogError(ex, "Error in ReportFileSystemChanged for {path}", path); _logger.LogError(ex, "Error in ReportFileSystemChanged for {path}", path);
} }
} }
} }
/// <summary>
/// Gets or sets the logger.
/// </summary>
/// <value>The logger.</value>
private ILogger Logger { get; set; }
private ILibraryManager LibraryManager { get; set; }
private IServerConfigurationManager ConfigurationManager { get; set; }
private readonly IFileSystem _fileSystem;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="LibraryMonitor" /> class. /// Initializes a new instance of the <see cref="LibraryMonitor" /> class.
/// </summary> /// </summary>
public LibraryMonitor( public LibraryMonitor(
ILoggerFactory loggerFactory, ILogger<LibraryMonitor> logger,
ILibraryManager libraryManager, ILibraryManager libraryManager,
IServerConfigurationManager configurationManager, IServerConfigurationManager configurationManager,
IFileSystem fileSystem) IFileSystem fileSystem)
{ {
LibraryManager = libraryManager; _libraryManager = libraryManager;
Logger = loggerFactory.CreateLogger(GetType().Name); _logger = logger;
ConfigurationManager = configurationManager; _configurationManager = configurationManager;
_fileSystem = fileSystem; _fileSystem = fileSystem;
} }
@ -151,7 +145,7 @@ namespace Emby.Server.Implementations.IO
return false; return false;
} }
var options = LibraryManager.GetLibraryOptions(item); var options = _libraryManager.GetLibraryOptions(item);
if (options != null) if (options != null)
{ {
@ -163,12 +157,12 @@ namespace Emby.Server.Implementations.IO
public void Start() public void Start()
{ {
LibraryManager.ItemAdded += OnLibraryManagerItemAdded; _libraryManager.ItemAdded += OnLibraryManagerItemAdded;
LibraryManager.ItemRemoved += OnLibraryManagerItemRemoved; _libraryManager.ItemRemoved += OnLibraryManagerItemRemoved;
var pathsToWatch = new List<string>(); var pathsToWatch = new List<string>();
var paths = LibraryManager var paths = _libraryManager
.RootFolder .RootFolder
.Children .Children
.Where(IsLibraryMonitorEnabled) .Where(IsLibraryMonitorEnabled)
@ -261,7 +255,7 @@ namespace Emby.Server.Implementations.IO
if (!Directory.Exists(path)) if (!Directory.Exists(path))
{ {
// Seeing a crash in the mono runtime due to an exception being thrown on a different thread // Seeing a crash in the mono runtime due to an exception being thrown on a different thread
Logger.LogInformation("Skipping realtime monitor for {Path} because the path does not exist", path); _logger.LogInformation("Skipping realtime monitor for {Path} because the path does not exist", path);
return; return;
} }
@ -297,7 +291,7 @@ namespace Emby.Server.Implementations.IO
if (_fileSystemWatchers.TryAdd(path, newWatcher)) if (_fileSystemWatchers.TryAdd(path, newWatcher))
{ {
newWatcher.EnableRaisingEvents = true; newWatcher.EnableRaisingEvents = true;
Logger.LogInformation("Watching directory " + path); _logger.LogInformation("Watching directory " + path);
} }
else else
{ {
@ -307,7 +301,7 @@ namespace Emby.Server.Implementations.IO
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.LogError(ex, "Error watching path: {path}", path); _logger.LogError(ex, "Error watching path: {path}", path);
} }
}); });
} }
@ -333,7 +327,7 @@ namespace Emby.Server.Implementations.IO
{ {
using (watcher) using (watcher)
{ {
Logger.LogInformation("Stopping directory watching for path {Path}", watcher.Path); _logger.LogInformation("Stopping directory watching for path {Path}", watcher.Path);
watcher.Created -= OnWatcherChanged; watcher.Created -= OnWatcherChanged;
watcher.Deleted -= OnWatcherChanged; watcher.Deleted -= OnWatcherChanged;
@ -372,7 +366,7 @@ namespace Emby.Server.Implementations.IO
var ex = e.GetException(); var ex = e.GetException();
var dw = (FileSystemWatcher)sender; var dw = (FileSystemWatcher)sender;
Logger.LogError(ex, "Error in Directory watcher for: {Path}", dw.Path); _logger.LogError(ex, "Error in Directory watcher for: {Path}", dw.Path);
DisposeWatcher(dw, true); DisposeWatcher(dw, true);
} }
@ -390,7 +384,7 @@ namespace Emby.Server.Implementations.IO
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.LogError(ex, "Exception in ReportFileSystemChanged. Path: {FullPath}", e.FullPath); _logger.LogError(ex, "Exception in ReportFileSystemChanged. Path: {FullPath}", e.FullPath);
} }
} }
@ -416,13 +410,13 @@ namespace Emby.Server.Implementations.IO
{ {
if (_fileSystem.AreEqual(i, path)) if (_fileSystem.AreEqual(i, path))
{ {
Logger.LogDebug("Ignoring change to {Path}", path); _logger.LogDebug("Ignoring change to {Path}", path);
return true; return true;
} }
if (_fileSystem.ContainsSubPath(i, path)) if (_fileSystem.ContainsSubPath(i, path))
{ {
Logger.LogDebug("Ignoring change to {Path}", path); _logger.LogDebug("Ignoring change to {Path}", path);
return true; return true;
} }
@ -430,7 +424,7 @@ namespace Emby.Server.Implementations.IO
var parent = Path.GetDirectoryName(i); var parent = Path.GetDirectoryName(i);
if (!string.IsNullOrEmpty(parent) && _fileSystem.AreEqual(parent, path)) if (!string.IsNullOrEmpty(parent) && _fileSystem.AreEqual(parent, path))
{ {
Logger.LogDebug("Ignoring change to {Path}", path); _logger.LogDebug("Ignoring change to {Path}", path);
return true; return true;
} }
@ -485,7 +479,7 @@ namespace Emby.Server.Implementations.IO
} }
} }
var newRefresher = new FileRefresher(path, ConfigurationManager, LibraryManager, Logger); var newRefresher = new FileRefresher(path, _configurationManager, _libraryManager, _logger);
newRefresher.Completed += NewRefresher_Completed; newRefresher.Completed += NewRefresher_Completed;
_activeRefreshers.Add(newRefresher); _activeRefreshers.Add(newRefresher);
} }
@ -502,8 +496,8 @@ namespace Emby.Server.Implementations.IO
/// </summary> /// </summary>
public void Stop() public void Stop()
{ {
LibraryManager.ItemAdded -= OnLibraryManagerItemAdded; _libraryManager.ItemAdded -= OnLibraryManagerItemAdded;
LibraryManager.ItemRemoved -= OnLibraryManagerItemRemoved; _libraryManager.ItemRemoved -= OnLibraryManagerItemRemoved;
foreach (var watcher in _fileSystemWatchers.Values.ToList()) foreach (var watcher in _fileSystemWatchers.Values.ToList())
{ {

@ -54,9 +54,29 @@ namespace Emby.Server.Implementations.Library
/// </summary> /// </summary>
public class LibraryManager : ILibraryManager public class LibraryManager : ILibraryManager
{ {
private readonly ILogger _logger;
private readonly ITaskManager _taskManager;
private readonly IUserManager _userManager;
private readonly IUserDataManager _userDataRepository;
private readonly IServerConfigurationManager _configurationManager;
private readonly Lazy<ILibraryMonitor> _libraryMonitorFactory;
private readonly Lazy<IProviderManager> _providerManagerFactory;
private readonly Lazy<IUserViewManager> _userviewManagerFactory;
private readonly IServerApplicationHost _appHost;
private readonly IMediaEncoder _mediaEncoder;
private readonly IFileSystem _fileSystem;
private readonly IItemRepository _itemRepository;
private readonly ConcurrentDictionary<Guid, BaseItem> _libraryItemsCache;
private NamingOptions _namingOptions; private NamingOptions _namingOptions;
private string[] _videoFileExtensions; private string[] _videoFileExtensions;
private ILibraryMonitor LibraryMonitor => _libraryMonitorFactory.Value;
private IProviderManager ProviderManager => _providerManagerFactory.Value;
private IUserViewManager UserViewManager => _userviewManagerFactory.Value;
/// <summary> /// <summary>
/// Gets or sets the postscan tasks. /// Gets or sets the postscan tasks.
/// </summary> /// </summary>
@ -89,12 +109,6 @@ namespace Emby.Server.Implementations.Library
/// <value>The comparers.</value> /// <value>The comparers.</value>
private IBaseItemComparer[] Comparers { get; set; } private IBaseItemComparer[] Comparers { get; set; }
/// <summary>
/// Gets or sets the active item repository
/// </summary>
/// <value>The item repository.</value>
public IItemRepository ItemRepository { get; set; }
/// <summary> /// <summary>
/// Occurs when [item added]. /// Occurs when [item added].
/// </summary> /// </summary>
@ -110,90 +124,47 @@ namespace Emby.Server.Implementations.Library
/// </summary> /// </summary>
public event EventHandler<ItemChangeEventArgs> ItemRemoved; public event EventHandler<ItemChangeEventArgs> ItemRemoved;
/// <summary>
/// The _logger
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// The _task manager
/// </summary>
private readonly ITaskManager _taskManager;
/// <summary>
/// The _user manager
/// </summary>
private readonly IUserManager _userManager;
/// <summary>
/// The _user data repository
/// </summary>
private readonly IUserDataManager _userDataRepository;
/// <summary>
/// Gets or sets the configuration manager.
/// </summary>
/// <value>The configuration manager.</value>
private IServerConfigurationManager ConfigurationManager { get; set; }
private readonly Func<ILibraryMonitor> _libraryMonitorFactory;
private readonly Func<IProviderManager> _providerManagerFactory;
private readonly Func<IUserViewManager> _userviewManager;
public bool IsScanRunning { get; private set; } public bool IsScanRunning { get; private set; }
private IServerApplicationHost _appHost;
private readonly IMediaEncoder _mediaEncoder;
/// <summary>
/// The _library items cache
/// </summary>
private readonly ConcurrentDictionary<Guid, BaseItem> _libraryItemsCache;
/// <summary>
/// Gets the library items cache.
/// </summary>
/// <value>The library items cache.</value>
private ConcurrentDictionary<Guid, BaseItem> LibraryItemsCache => _libraryItemsCache;
private readonly IFileSystem _fileSystem;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="LibraryManager" /> class. /// Initializes a new instance of the <see cref="LibraryManager" /> class.
/// </summary> /// </summary>
/// <param name="appHost">The application host</param> /// <param name="appHost">The application host</param>
/// <param name="loggerFactory">The logger factory.</param> /// <param name="logger">The logger.</param>
/// <param name="taskManager">The task manager.</param> /// <param name="taskManager">The task manager.</param>
/// <param name="userManager">The user manager.</param> /// <param name="userManager">The user manager.</param>
/// <param name="configurationManager">The configuration manager.</param> /// <param name="configurationManager">The configuration manager.</param>
/// <param name="userDataRepository">The user data repository.</param> /// <param name="userDataRepository">The user data repository.</param>
public LibraryManager( public LibraryManager(
IServerApplicationHost appHost, IServerApplicationHost appHost,
ILoggerFactory loggerFactory, ILogger<LibraryManager> logger,
ITaskManager taskManager, ITaskManager taskManager,
IUserManager userManager, IUserManager userManager,
IServerConfigurationManager configurationManager, IServerConfigurationManager configurationManager,
IUserDataManager userDataRepository, IUserDataManager userDataRepository,
Func<ILibraryMonitor> libraryMonitorFactory, Lazy<ILibraryMonitor> libraryMonitorFactory,
IFileSystem fileSystem, IFileSystem fileSystem,
Func<IProviderManager> providerManagerFactory, Lazy<IProviderManager> providerManagerFactory,
Func<IUserViewManager> userviewManager, Lazy<IUserViewManager> userviewManagerFactory,
IMediaEncoder mediaEncoder) IMediaEncoder mediaEncoder,
IItemRepository itemRepository)
{ {
_appHost = appHost; _appHost = appHost;
_logger = loggerFactory.CreateLogger(nameof(LibraryManager)); _logger = logger;
_taskManager = taskManager; _taskManager = taskManager;
_userManager = userManager; _userManager = userManager;
ConfigurationManager = configurationManager; _configurationManager = configurationManager;
_userDataRepository = userDataRepository; _userDataRepository = userDataRepository;
_libraryMonitorFactory = libraryMonitorFactory; _libraryMonitorFactory = libraryMonitorFactory;
_fileSystem = fileSystem; _fileSystem = fileSystem;
_providerManagerFactory = providerManagerFactory; _providerManagerFactory = providerManagerFactory;
_userviewManager = userviewManager; _userviewManagerFactory = userviewManagerFactory;
_mediaEncoder = mediaEncoder; _mediaEncoder = mediaEncoder;
_itemRepository = itemRepository;
_libraryItemsCache = new ConcurrentDictionary<Guid, BaseItem>(); _libraryItemsCache = new ConcurrentDictionary<Guid, BaseItem>();
ConfigurationManager.ConfigurationUpdated += ConfigurationUpdated; _configurationManager.ConfigurationUpdated += ConfigurationUpdated;
RecordConfigurationValues(configurationManager.Configuration); RecordConfigurationValues(configurationManager.Configuration);
} }
@ -272,7 +243,7 @@ namespace Emby.Server.Implementations.Library
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
private void ConfigurationUpdated(object sender, EventArgs e) private void ConfigurationUpdated(object sender, EventArgs e)
{ {
var config = ConfigurationManager.Configuration; var config = _configurationManager.Configuration;
var wizardChanged = config.IsStartupWizardCompleted != _wizardCompleted; var wizardChanged = config.IsStartupWizardCompleted != _wizardCompleted;
@ -306,7 +277,7 @@ namespace Emby.Server.Implementations.Library
} }
} }
LibraryItemsCache.AddOrUpdate(item.Id, item, delegate { return item; }); _libraryItemsCache.AddOrUpdate(item.Id, item, delegate { return item; });
} }
public void DeleteItem(BaseItem item, DeleteOptions options) public void DeleteItem(BaseItem item, DeleteOptions options)
@ -437,10 +408,10 @@ namespace Emby.Server.Implementations.Library
item.SetParent(null); item.SetParent(null);
ItemRepository.DeleteItem(item.Id); _itemRepository.DeleteItem(item.Id);
foreach (var child in children) foreach (var child in children)
{ {
ItemRepository.DeleteItem(child.Id); _itemRepository.DeleteItem(child.Id);
} }
_libraryItemsCache.TryRemove(item.Id, out BaseItem removed); _libraryItemsCache.TryRemove(item.Id, out BaseItem removed);
@ -509,15 +480,15 @@ namespace Emby.Server.Implementations.Library
throw new ArgumentNullException(nameof(type)); throw new ArgumentNullException(nameof(type));
} }
if (key.StartsWith(ConfigurationManager.ApplicationPaths.ProgramDataPath, StringComparison.Ordinal)) if (key.StartsWith(_configurationManager.ApplicationPaths.ProgramDataPath, StringComparison.Ordinal))
{ {
// Try to normalize paths located underneath program-data in an attempt to make them more portable // Try to normalize paths located underneath program-data in an attempt to make them more portable
key = key.Substring(ConfigurationManager.ApplicationPaths.ProgramDataPath.Length) key = key.Substring(_configurationManager.ApplicationPaths.ProgramDataPath.Length)
.TrimStart(new[] { '/', '\\' }) .TrimStart(new[] { '/', '\\' })
.Replace("/", "\\"); .Replace("/", "\\");
} }
if (forceCaseInsensitive || !ConfigurationManager.Configuration.EnableCaseSensitiveItemIds) if (forceCaseInsensitive || !_configurationManager.Configuration.EnableCaseSensitiveItemIds)
{ {
key = key.ToLowerInvariant(); key = key.ToLowerInvariant();
} }
@ -550,7 +521,7 @@ namespace Emby.Server.Implementations.Library
collectionType = GetContentTypeOverride(fullPath, true); collectionType = GetContentTypeOverride(fullPath, true);
} }
var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths, directoryService) var args = new ItemResolveArgs(_configurationManager.ApplicationPaths, directoryService)
{ {
Parent = parent, Parent = parent,
Path = fullPath, Path = fullPath,
@ -720,7 +691,7 @@ namespace Emby.Server.Implementations.Library
/// <exception cref="InvalidOperationException">Cannot create the root folder until plugins have loaded.</exception> /// <exception cref="InvalidOperationException">Cannot create the root folder until plugins have loaded.</exception>
public AggregateFolder CreateRootFolder() public AggregateFolder CreateRootFolder()
{ {
var rootFolderPath = ConfigurationManager.ApplicationPaths.RootFolderPath; var rootFolderPath = _configurationManager.ApplicationPaths.RootFolderPath;
Directory.CreateDirectory(rootFolderPath); Directory.CreateDirectory(rootFolderPath);
@ -734,7 +705,7 @@ namespace Emby.Server.Implementations.Library
} }
// Add in the plug-in folders // Add in the plug-in folders
var path = Path.Combine(ConfigurationManager.ApplicationPaths.DataPath, "playlists"); var path = Path.Combine(_configurationManager.ApplicationPaths.DataPath, "playlists");
Directory.CreateDirectory(path); Directory.CreateDirectory(path);
@ -786,7 +757,7 @@ namespace Emby.Server.Implementations.Library
{ {
if (_userRootFolder == null) if (_userRootFolder == null)
{ {
var userRootPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; var userRootPath = _configurationManager.ApplicationPaths.DefaultUserViewsPath;
_logger.LogDebug("Creating userRootPath at {path}", userRootPath); _logger.LogDebug("Creating userRootPath at {path}", userRootPath);
Directory.CreateDirectory(userRootPath); Directory.CreateDirectory(userRootPath);
@ -980,7 +951,7 @@ namespace Emby.Server.Implementations.Library
where T : BaseItem, new() where T : BaseItem, new()
{ {
var path = getPathFn(name); var path = getPathFn(name);
var forceCaseInsensitiveId = ConfigurationManager.Configuration.EnableNormalizedItemByNameIds; var forceCaseInsensitiveId = _configurationManager.Configuration.EnableNormalizedItemByNameIds;
return GetNewItemIdInternal(path, typeof(T), forceCaseInsensitiveId); return GetNewItemIdInternal(path, typeof(T), forceCaseInsensitiveId);
} }
@ -994,7 +965,7 @@ namespace Emby.Server.Implementations.Library
public Task ValidatePeople(CancellationToken cancellationToken, IProgress<double> progress) public Task ValidatePeople(CancellationToken cancellationToken, IProgress<double> progress)
{ {
// Ensure the location is available. // Ensure the location is available.
Directory.CreateDirectory(ConfigurationManager.ApplicationPaths.PeoplePath); Directory.CreateDirectory(_configurationManager.ApplicationPaths.PeoplePath);
return new PeopleValidator(this, _logger, _fileSystem).ValidatePeople(cancellationToken, progress); return new PeopleValidator(this, _logger, _fileSystem).ValidatePeople(cancellationToken, progress);
} }
@ -1031,7 +1002,7 @@ namespace Emby.Server.Implementations.Library
public async Task ValidateMediaLibraryInternal(IProgress<double> progress, CancellationToken cancellationToken) public async Task ValidateMediaLibraryInternal(IProgress<double> progress, CancellationToken cancellationToken)
{ {
IsScanRunning = true; IsScanRunning = true;
_libraryMonitorFactory().Stop(); LibraryMonitor.Stop();
try try
{ {
@ -1039,7 +1010,7 @@ namespace Emby.Server.Implementations.Library
} }
finally finally
{ {
_libraryMonitorFactory().Start(); LibraryMonitor.Start();
IsScanRunning = false; IsScanRunning = false;
} }
} }
@ -1148,7 +1119,7 @@ namespace Emby.Server.Implementations.Library
progress.Report(percent * 100); progress.Report(percent * 100);
} }
ItemRepository.UpdateInheritedValues(cancellationToken); _itemRepository.UpdateInheritedValues(cancellationToken);
progress.Report(100); progress.Report(100);
} }
@ -1168,9 +1139,9 @@ namespace Emby.Server.Implementations.Library
var topLibraryFolders = GetUserRootFolder().Children.ToList(); var topLibraryFolders = GetUserRootFolder().Children.ToList();
_logger.LogDebug("Getting refreshQueue"); _logger.LogDebug("Getting refreshQueue");
var refreshQueue = includeRefreshState ? _providerManagerFactory().GetRefreshQueue() : null; var refreshQueue = includeRefreshState ? ProviderManager.GetRefreshQueue() : null;
return _fileSystem.GetDirectoryPaths(ConfigurationManager.ApplicationPaths.DefaultUserViewsPath) return _fileSystem.GetDirectoryPaths(_configurationManager.ApplicationPaths.DefaultUserViewsPath)
.Select(dir => GetVirtualFolderInfo(dir, topLibraryFolders, refreshQueue)) .Select(dir => GetVirtualFolderInfo(dir, topLibraryFolders, refreshQueue))
.ToList(); .ToList();
} }
@ -1245,7 +1216,7 @@ namespace Emby.Server.Implementations.Library
throw new ArgumentException("Guid can't be empty", nameof(id)); throw new ArgumentException("Guid can't be empty", nameof(id));
} }
if (LibraryItemsCache.TryGetValue(id, out BaseItem item)) if (_libraryItemsCache.TryGetValue(id, out BaseItem item))
{ {
return item; return item;
} }
@ -1276,7 +1247,7 @@ namespace Emby.Server.Implementations.Library
AddUserToQuery(query, query.User, allowExternalContent); AddUserToQuery(query, query.User, allowExternalContent);
} }
return ItemRepository.GetItemList(query); return _itemRepository.GetItemList(query);
} }
public List<BaseItem> GetItemList(InternalItemsQuery query) public List<BaseItem> GetItemList(InternalItemsQuery query)
@ -1300,7 +1271,7 @@ namespace Emby.Server.Implementations.Library
AddUserToQuery(query, query.User); AddUserToQuery(query, query.User);
} }
return ItemRepository.GetCount(query); return _itemRepository.GetCount(query);
} }
public List<BaseItem> GetItemList(InternalItemsQuery query, List<BaseItem> parents) public List<BaseItem> GetItemList(InternalItemsQuery query, List<BaseItem> parents)
@ -1315,7 +1286,7 @@ namespace Emby.Server.Implementations.Library
} }
} }
return ItemRepository.GetItemList(query); return _itemRepository.GetItemList(query);
} }
public QueryResult<BaseItem> QueryItems(InternalItemsQuery query) public QueryResult<BaseItem> QueryItems(InternalItemsQuery query)
@ -1327,12 +1298,12 @@ namespace Emby.Server.Implementations.Library
if (query.EnableTotalRecordCount) if (query.EnableTotalRecordCount)
{ {
return ItemRepository.GetItems(query); return _itemRepository.GetItems(query);
} }
return new QueryResult<BaseItem> return new QueryResult<BaseItem>
{ {
Items = ItemRepository.GetItemList(query).ToArray() Items = _itemRepository.GetItemList(query).ToArray()
}; };
} }
@ -1343,7 +1314,7 @@ namespace Emby.Server.Implementations.Library
AddUserToQuery(query, query.User); AddUserToQuery(query, query.User);
} }
return ItemRepository.GetItemIdsList(query); return _itemRepository.GetItemIdsList(query);
} }
public QueryResult<(BaseItem, ItemCounts)> GetStudios(InternalItemsQuery query) public QueryResult<(BaseItem, ItemCounts)> GetStudios(InternalItemsQuery query)
@ -1354,7 +1325,7 @@ namespace Emby.Server.Implementations.Library
} }
SetTopParentOrAncestorIds(query); SetTopParentOrAncestorIds(query);
return ItemRepository.GetStudios(query); return _itemRepository.GetStudios(query);
} }
public QueryResult<(BaseItem, ItemCounts)> GetGenres(InternalItemsQuery query) public QueryResult<(BaseItem, ItemCounts)> GetGenres(InternalItemsQuery query)
@ -1365,7 +1336,7 @@ namespace Emby.Server.Implementations.Library
} }
SetTopParentOrAncestorIds(query); SetTopParentOrAncestorIds(query);
return ItemRepository.GetGenres(query); return _itemRepository.GetGenres(query);
} }
public QueryResult<(BaseItem, ItemCounts)> GetMusicGenres(InternalItemsQuery query) public QueryResult<(BaseItem, ItemCounts)> GetMusicGenres(InternalItemsQuery query)
@ -1376,7 +1347,7 @@ namespace Emby.Server.Implementations.Library
} }
SetTopParentOrAncestorIds(query); SetTopParentOrAncestorIds(query);
return ItemRepository.GetMusicGenres(query); return _itemRepository.GetMusicGenres(query);
} }
public QueryResult<(BaseItem, ItemCounts)> GetAllArtists(InternalItemsQuery query) public QueryResult<(BaseItem, ItemCounts)> GetAllArtists(InternalItemsQuery query)
@ -1387,7 +1358,7 @@ namespace Emby.Server.Implementations.Library
} }
SetTopParentOrAncestorIds(query); SetTopParentOrAncestorIds(query);
return ItemRepository.GetAllArtists(query); return _itemRepository.GetAllArtists(query);
} }
public QueryResult<(BaseItem, ItemCounts)> GetArtists(InternalItemsQuery query) public QueryResult<(BaseItem, ItemCounts)> GetArtists(InternalItemsQuery query)
@ -1398,7 +1369,7 @@ namespace Emby.Server.Implementations.Library
} }
SetTopParentOrAncestorIds(query); SetTopParentOrAncestorIds(query);
return ItemRepository.GetArtists(query); return _itemRepository.GetArtists(query);
} }
private void SetTopParentOrAncestorIds(InternalItemsQuery query) private void SetTopParentOrAncestorIds(InternalItemsQuery query)
@ -1439,7 +1410,7 @@ namespace Emby.Server.Implementations.Library
} }
SetTopParentOrAncestorIds(query); SetTopParentOrAncestorIds(query);
return ItemRepository.GetAlbumArtists(query); return _itemRepository.GetAlbumArtists(query);
} }
public QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query) public QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query)
@ -1460,10 +1431,10 @@ namespace Emby.Server.Implementations.Library
if (query.EnableTotalRecordCount) if (query.EnableTotalRecordCount)
{ {
return ItemRepository.GetItems(query); return _itemRepository.GetItems(query);
} }
var list = ItemRepository.GetItemList(query); var list = _itemRepository.GetItemList(query);
return new QueryResult<BaseItem> return new QueryResult<BaseItem>
{ {
@ -1509,7 +1480,7 @@ namespace Emby.Server.Implementations.Library
string.IsNullOrEmpty(query.SeriesPresentationUniqueKey) && string.IsNullOrEmpty(query.SeriesPresentationUniqueKey) &&
query.ItemIds.Length == 0) query.ItemIds.Length == 0)
{ {
var userViews = _userviewManager().GetUserViews(new UserViewQuery var userViews = UserViewManager.GetUserViews(new UserViewQuery
{ {
UserId = user.Id, UserId = user.Id,
IncludeHidden = true, IncludeHidden = true,
@ -1809,7 +1780,7 @@ namespace Emby.Server.Implementations.Library
// Don't iterate multiple times // Don't iterate multiple times
var itemsList = items.ToList(); var itemsList = items.ToList();
ItemRepository.SaveItems(itemsList, cancellationToken); _itemRepository.SaveItems(itemsList, cancellationToken);
foreach (var item in itemsList) foreach (var item in itemsList)
{ {
@ -1846,7 +1817,7 @@ namespace Emby.Server.Implementations.Library
public void UpdateImages(BaseItem item) public void UpdateImages(BaseItem item)
{ {
ItemRepository.SaveImages(item); _itemRepository.SaveImages(item);
RegisterItem(item); RegisterItem(item);
} }
@ -1863,7 +1834,7 @@ namespace Emby.Server.Implementations.Library
{ {
if (item.IsFileProtocol) if (item.IsFileProtocol)
{ {
_providerManagerFactory().SaveMetadata(item, updateReason); ProviderManager.SaveMetadata(item, updateReason);
} }
item.DateLastSaved = DateTime.UtcNow; item.DateLastSaved = DateTime.UtcNow;
@ -1871,7 +1842,7 @@ namespace Emby.Server.Implementations.Library
RegisterItem(item); RegisterItem(item);
} }
ItemRepository.SaveItems(itemsList, cancellationToken); _itemRepository.SaveItems(itemsList, cancellationToken);
if (ItemUpdated != null) if (ItemUpdated != null)
{ {
@ -1947,7 +1918,7 @@ namespace Emby.Server.Implementations.Library
/// <returns>BaseItem.</returns> /// <returns>BaseItem.</returns>
public BaseItem RetrieveItem(Guid id) public BaseItem RetrieveItem(Guid id)
{ {
return ItemRepository.RetrieveItem(id); return _itemRepository.RetrieveItem(id);
} }
public List<Folder> GetCollectionFolders(BaseItem item) public List<Folder> GetCollectionFolders(BaseItem item)
@ -2066,7 +2037,7 @@ namespace Emby.Server.Implementations.Library
private string GetContentTypeOverride(string path, bool inherit) private string GetContentTypeOverride(string path, bool inherit)
{ {
var nameValuePair = ConfigurationManager.Configuration.ContentTypes var nameValuePair = _configurationManager.Configuration.ContentTypes
.FirstOrDefault(i => _fileSystem.AreEqual(i.Name, path) .FirstOrDefault(i => _fileSystem.AreEqual(i.Name, path)
|| (inherit && !string.IsNullOrEmpty(i.Name) || (inherit && !string.IsNullOrEmpty(i.Name)
&& _fileSystem.ContainsSubPath(i.Name, path))); && _fileSystem.ContainsSubPath(i.Name, path)));
@ -2115,7 +2086,7 @@ namespace Emby.Server.Implementations.Library
string sortName) string sortName)
{ {
var path = Path.Combine( var path = Path.Combine(
ConfigurationManager.ApplicationPaths.InternalMetadataPath, _configurationManager.ApplicationPaths.InternalMetadataPath,
"views", "views",
_fileSystem.GetValidFilename(viewType)); _fileSystem.GetValidFilename(viewType));
@ -2147,7 +2118,7 @@ namespace Emby.Server.Implementations.Library
if (refresh) if (refresh)
{ {
item.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None); item.UpdateToRepository(ItemUpdateType.MetadataImport, CancellationToken.None);
_providerManagerFactory().QueueRefresh(item.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), RefreshPriority.Normal); ProviderManager.QueueRefresh(item.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), RefreshPriority.Normal);
} }
return item; return item;
@ -2165,7 +2136,7 @@ namespace Emby.Server.Implementations.Library
var id = GetNewItemId(idValues, typeof(UserView)); var id = GetNewItemId(idValues, typeof(UserView));
var path = Path.Combine(ConfigurationManager.ApplicationPaths.InternalMetadataPath, "views", id.ToString("N", CultureInfo.InvariantCulture)); var path = Path.Combine(_configurationManager.ApplicationPaths.InternalMetadataPath, "views", id.ToString("N", CultureInfo.InvariantCulture));
var item = GetItemById(id) as UserView; var item = GetItemById(id) as UserView;
@ -2202,7 +2173,7 @@ namespace Emby.Server.Implementations.Library
if (refresh) if (refresh)
{ {
_providerManagerFactory().QueueRefresh( ProviderManager.QueueRefresh(
item.Id, item.Id,
new MetadataRefreshOptions(new DirectoryService(_fileSystem)) new MetadataRefreshOptions(new DirectoryService(_fileSystem))
{ {
@ -2269,7 +2240,7 @@ namespace Emby.Server.Implementations.Library
if (refresh) if (refresh)
{ {
_providerManagerFactory().QueueRefresh( ProviderManager.QueueRefresh(
item.Id, item.Id,
new MetadataRefreshOptions(new DirectoryService(_fileSystem)) new MetadataRefreshOptions(new DirectoryService(_fileSystem))
{ {
@ -2303,7 +2274,7 @@ namespace Emby.Server.Implementations.Library
var id = GetNewItemId(idValues, typeof(UserView)); var id = GetNewItemId(idValues, typeof(UserView));
var path = Path.Combine(ConfigurationManager.ApplicationPaths.InternalMetadataPath, "views", id.ToString("N", CultureInfo.InvariantCulture)); var path = Path.Combine(_configurationManager.ApplicationPaths.InternalMetadataPath, "views", id.ToString("N", CultureInfo.InvariantCulture));
var item = GetItemById(id) as UserView; var item = GetItemById(id) as UserView;
@ -2346,7 +2317,7 @@ namespace Emby.Server.Implementations.Library
if (refresh) if (refresh)
{ {
_providerManagerFactory().QueueRefresh( ProviderManager.QueueRefresh(
item.Id, item.Id,
new MetadataRefreshOptions(new DirectoryService(_fileSystem)) new MetadataRefreshOptions(new DirectoryService(_fileSystem))
{ {
@ -2675,8 +2646,8 @@ namespace Emby.Server.Implementations.Library
} }
} }
var metadataPath = ConfigurationManager.Configuration.MetadataPath; var metadataPath = _configurationManager.Configuration.MetadataPath;
var metadataNetworkPath = ConfigurationManager.Configuration.MetadataNetworkPath; var metadataNetworkPath = _configurationManager.Configuration.MetadataNetworkPath;
if (!string.IsNullOrWhiteSpace(metadataPath) && !string.IsNullOrWhiteSpace(metadataNetworkPath)) if (!string.IsNullOrWhiteSpace(metadataPath) && !string.IsNullOrWhiteSpace(metadataNetworkPath))
{ {
@ -2687,7 +2658,7 @@ namespace Emby.Server.Implementations.Library
} }
} }
foreach (var map in ConfigurationManager.Configuration.PathSubstitutions) foreach (var map in _configurationManager.Configuration.PathSubstitutions)
{ {
if (!string.IsNullOrWhiteSpace(map.From)) if (!string.IsNullOrWhiteSpace(map.From))
{ {
@ -2756,7 +2727,7 @@ namespace Emby.Server.Implementations.Library
public List<PersonInfo> GetPeople(InternalPeopleQuery query) public List<PersonInfo> GetPeople(InternalPeopleQuery query)
{ {
return ItemRepository.GetPeople(query); return _itemRepository.GetPeople(query);
} }
public List<PersonInfo> GetPeople(BaseItem item) public List<PersonInfo> GetPeople(BaseItem item)
@ -2779,7 +2750,7 @@ namespace Emby.Server.Implementations.Library
public List<Person> GetPeopleItems(InternalPeopleQuery query) public List<Person> GetPeopleItems(InternalPeopleQuery query)
{ {
return ItemRepository.GetPeopleNames(query).Select(i => return _itemRepository.GetPeopleNames(query).Select(i =>
{ {
try try
{ {
@ -2796,7 +2767,7 @@ namespace Emby.Server.Implementations.Library
public List<string> GetPeopleNames(InternalPeopleQuery query) public List<string> GetPeopleNames(InternalPeopleQuery query)
{ {
return ItemRepository.GetPeopleNames(query); return _itemRepository.GetPeopleNames(query);
} }
public void UpdatePeople(BaseItem item, List<PersonInfo> people) public void UpdatePeople(BaseItem item, List<PersonInfo> people)
@ -2806,7 +2777,7 @@ namespace Emby.Server.Implementations.Library
return; return;
} }
ItemRepository.UpdatePeople(item.Id, people); _itemRepository.UpdatePeople(item.Id, people);
} }
public async Task<ItemImageInfo> ConvertImageToLocal(BaseItem item, ItemImageInfo image, int imageIndex) public async Task<ItemImageInfo> ConvertImageToLocal(BaseItem item, ItemImageInfo image, int imageIndex)
@ -2817,7 +2788,7 @@ namespace Emby.Server.Implementations.Library
{ {
_logger.LogDebug("ConvertImageToLocal item {0} - image url: {1}", item.Id, url); _logger.LogDebug("ConvertImageToLocal item {0} - image url: {1}", item.Id, url);
await _providerManagerFactory().SaveImage(item, url, image.Type, imageIndex, CancellationToken.None).ConfigureAwait(false); await ProviderManager.SaveImage(item, url, image.Type, imageIndex, CancellationToken.None).ConfigureAwait(false);
item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None);
@ -2850,7 +2821,7 @@ namespace Emby.Server.Implementations.Library
name = _fileSystem.GetValidFilename(name); name = _fileSystem.GetValidFilename(name);
var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; var rootFolderPath = _configurationManager.ApplicationPaths.DefaultUserViewsPath;
var virtualFolderPath = Path.Combine(rootFolderPath, name); var virtualFolderPath = Path.Combine(rootFolderPath, name);
while (Directory.Exists(virtualFolderPath)) while (Directory.Exists(virtualFolderPath))
@ -2869,7 +2840,7 @@ namespace Emby.Server.Implementations.Library
} }
} }
_libraryMonitorFactory().Stop(); LibraryMonitor.Stop();
try try
{ {
@ -2904,7 +2875,7 @@ namespace Emby.Server.Implementations.Library
{ {
// Need to add a delay here or directory watchers may still pick up the changes // Need to add a delay here or directory watchers may still pick up the changes
await Task.Delay(1000).ConfigureAwait(false); await Task.Delay(1000).ConfigureAwait(false);
_libraryMonitorFactory().Start(); LibraryMonitor.Start();
} }
} }
} }
@ -2964,7 +2935,7 @@ namespace Emby.Server.Implementations.Library
throw new FileNotFoundException("The network path does not exist."); throw new FileNotFoundException("The network path does not exist.");
} }
var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; var rootFolderPath = _configurationManager.ApplicationPaths.DefaultUserViewsPath;
var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName); var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName);
var shortcutFilename = Path.GetFileNameWithoutExtension(path); var shortcutFilename = Path.GetFileNameWithoutExtension(path);
@ -3007,7 +2978,7 @@ namespace Emby.Server.Implementations.Library
throw new FileNotFoundException("The network path does not exist."); throw new FileNotFoundException("The network path does not exist.");
} }
var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; var rootFolderPath = _configurationManager.ApplicationPaths.DefaultUserViewsPath;
var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName); var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName);
var libraryOptions = CollectionFolder.GetLibraryOptions(virtualFolderPath); var libraryOptions = CollectionFolder.GetLibraryOptions(virtualFolderPath);
@ -3060,7 +3031,7 @@ namespace Emby.Server.Implementations.Library
throw new ArgumentNullException(nameof(name)); throw new ArgumentNullException(nameof(name));
} }
var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; var rootFolderPath = _configurationManager.ApplicationPaths.DefaultUserViewsPath;
var path = Path.Combine(rootFolderPath, name); var path = Path.Combine(rootFolderPath, name);
@ -3069,7 +3040,7 @@ namespace Emby.Server.Implementations.Library
throw new FileNotFoundException("The media folder does not exist"); throw new FileNotFoundException("The media folder does not exist");
} }
_libraryMonitorFactory().Stop(); LibraryMonitor.Stop();
try try
{ {
@ -3089,7 +3060,7 @@ namespace Emby.Server.Implementations.Library
{ {
// Need to add a delay here or directory watchers may still pick up the changes // Need to add a delay here or directory watchers may still pick up the changes
await Task.Delay(1000).ConfigureAwait(false); await Task.Delay(1000).ConfigureAwait(false);
_libraryMonitorFactory().Start(); LibraryMonitor.Start();
} }
} }
} }
@ -3103,7 +3074,7 @@ namespace Emby.Server.Implementations.Library
var removeList = new List<NameValuePair>(); var removeList = new List<NameValuePair>();
foreach (var contentType in ConfigurationManager.Configuration.ContentTypes) foreach (var contentType in _configurationManager.Configuration.ContentTypes)
{ {
if (string.IsNullOrWhiteSpace(contentType.Name)) if (string.IsNullOrWhiteSpace(contentType.Name))
{ {
@ -3118,11 +3089,11 @@ namespace Emby.Server.Implementations.Library
if (removeList.Count > 0) if (removeList.Count > 0)
{ {
ConfigurationManager.Configuration.ContentTypes = ConfigurationManager.Configuration.ContentTypes _configurationManager.Configuration.ContentTypes = _configurationManager.Configuration.ContentTypes
.Except(removeList) .Except(removeList)
.ToArray(); .ToArray();
ConfigurationManager.SaveConfiguration(); _configurationManager.SaveConfiguration();
} }
} }
@ -3133,7 +3104,7 @@ namespace Emby.Server.Implementations.Library
throw new ArgumentNullException(nameof(mediaPath)); throw new ArgumentNullException(nameof(mediaPath));
} }
var rootFolderPath = ConfigurationManager.ApplicationPaths.DefaultUserViewsPath; var rootFolderPath = _configurationManager.ApplicationPaths.DefaultUserViewsPath;
var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName); var virtualFolderPath = Path.Combine(rootFolderPath, virtualFolderName);
if (!Directory.Exists(virtualFolderPath)) if (!Directory.Exists(virtualFolderPath))

@ -33,13 +33,13 @@ namespace Emby.Server.Implementations.Library
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly IJsonSerializer _jsonSerializer; private readonly IJsonSerializer _jsonSerializer;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private IMediaSourceProvider[] _providers;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IUserDataManager _userDataManager; private readonly IUserDataManager _userDataManager;
private readonly Func<IMediaEncoder> _mediaEncoder; private readonly IMediaEncoder _mediaEncoder;
private ILocalizationManager _localizationManager; private readonly ILocalizationManager _localizationManager;
private IApplicationPaths _appPaths; private readonly IApplicationPaths _appPaths;
private IMediaSourceProvider[] _providers;
public MediaSourceManager( public MediaSourceManager(
IItemRepository itemRepo, IItemRepository itemRepo,
@ -47,16 +47,16 @@ namespace Emby.Server.Implementations.Library
ILocalizationManager localizationManager, ILocalizationManager localizationManager,
IUserManager userManager, IUserManager userManager,
ILibraryManager libraryManager, ILibraryManager libraryManager,
ILoggerFactory loggerFactory, ILogger<MediaSourceManager> logger,
IJsonSerializer jsonSerializer, IJsonSerializer jsonSerializer,
IFileSystem fileSystem, IFileSystem fileSystem,
IUserDataManager userDataManager, IUserDataManager userDataManager,
Func<IMediaEncoder> mediaEncoder) IMediaEncoder mediaEncoder)
{ {
_itemRepo = itemRepo; _itemRepo = itemRepo;
_userManager = userManager; _userManager = userManager;
_libraryManager = libraryManager; _libraryManager = libraryManager;
_logger = loggerFactory.CreateLogger(nameof(MediaSourceManager)); _logger = logger;
_jsonSerializer = jsonSerializer; _jsonSerializer = jsonSerializer;
_fileSystem = fileSystem; _fileSystem = fileSystem;
_userDataManager = userDataManager; _userDataManager = userDataManager;
@ -496,7 +496,7 @@ namespace Emby.Server.Implementations.Library
// hack - these two values were taken from LiveTVMediaSourceProvider // hack - these two values were taken from LiveTVMediaSourceProvider
string cacheKey = request.OpenToken; string cacheKey = request.OpenToken;
await new LiveStreamHelper(_mediaEncoder(), _logger, _jsonSerializer, _appPaths) await new LiveStreamHelper(_mediaEncoder, _logger, _jsonSerializer, _appPaths)
.AddMediaInfoWithProbe(mediaSource, isAudio, cacheKey, true, cancellationToken) .AddMediaInfoWithProbe(mediaSource, isAudio, cacheKey, true, cancellationToken)
.ConfigureAwait(false); .ConfigureAwait(false);
} }
@ -621,7 +621,7 @@ namespace Emby.Server.Implementations.Library
if (liveStreamInfo is IDirectStreamProvider) if (liveStreamInfo is IDirectStreamProvider)
{ {
var info = await _mediaEncoder().GetMediaInfo(new MediaInfoRequest var info = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest
{ {
MediaSource = mediaSource, MediaSource = mediaSource,
ExtractChapters = false, ExtractChapters = false,
@ -674,7 +674,7 @@ namespace Emby.Server.Implementations.Library
mediaSource.AnalyzeDurationMs = 3000; mediaSource.AnalyzeDurationMs = 3000;
} }
mediaInfo = await _mediaEncoder().GetMediaInfo(new MediaInfoRequest mediaInfo = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest
{ {
MediaSource = mediaSource, MediaSource = mediaSource,
MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video, MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video,

@ -17,16 +17,15 @@ namespace Emby.Server.Implementations.Library
{ {
public class SearchEngine : ISearchEngine public class SearchEngine : ISearchEngine
{ {
private readonly ILogger _logger;
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly IUserManager _userManager; private readonly IUserManager _userManager;
private readonly ILogger _logger;
public SearchEngine(ILoggerFactory loggerFactory, ILibraryManager libraryManager, IUserManager userManager) public SearchEngine(ILogger<SearchEngine> logger, ILibraryManager libraryManager, IUserManager userManager)
{ {
_logger = logger;
_libraryManager = libraryManager; _libraryManager = libraryManager;
_userManager = userManager; _userManager = userManager;
_logger = loggerFactory.CreateLogger("SearchEngine");
} }
public QueryResult<SearchHintInfo> GetSearchHints(SearchQuery query) public QueryResult<SearchHintInfo> GetSearchHints(SearchQuery query)

@ -28,25 +28,24 @@ namespace Emby.Server.Implementations.Library
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IServerConfigurationManager _config; private readonly IServerConfigurationManager _config;
private readonly IUserManager _userManager;
private Func<IUserManager> _userManager; private readonly IUserDataRepository _repository;
public UserDataManager(ILoggerFactory loggerFactory, IServerConfigurationManager config, Func<IUserManager> userManager) public UserDataManager(
ILogger<UserDataManager> logger,
IServerConfigurationManager config,
IUserManager userManager,
IUserDataRepository repository)
{ {
_logger = logger;
_config = config; _config = config;
_logger = loggerFactory.CreateLogger(GetType().Name);
_userManager = userManager; _userManager = userManager;
_repository = repository;
} }
/// <summary>
/// Gets or sets the repository.
/// </summary>
/// <value>The repository.</value>
public IUserDataRepository Repository { get; set; }
public void SaveUserData(Guid userId, BaseItem item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken) public void SaveUserData(Guid userId, BaseItem item, UserItemData userData, UserDataSaveReason reason, CancellationToken cancellationToken)
{ {
var user = _userManager().GetUserById(userId); var user = _userManager.GetUserById(userId);
SaveUserData(user, item, userData, reason, cancellationToken); SaveUserData(user, item, userData, reason, cancellationToken);
} }
@ -71,7 +70,7 @@ namespace Emby.Server.Implementations.Library
foreach (var key in keys) foreach (var key in keys)
{ {
Repository.SaveUserData(userId, key, userData, cancellationToken); _repository.SaveUserData(userId, key, userData, cancellationToken);
} }
var cacheKey = GetCacheKey(userId, item.Id); var cacheKey = GetCacheKey(userId, item.Id);
@ -96,9 +95,9 @@ namespace Emby.Server.Implementations.Library
/// <returns></returns> /// <returns></returns>
public void SaveAllUserData(Guid userId, UserItemData[] userData, CancellationToken cancellationToken) public void SaveAllUserData(Guid userId, UserItemData[] userData, CancellationToken cancellationToken)
{ {
var user = _userManager().GetUserById(userId); var user = _userManager.GetUserById(userId);
Repository.SaveAllUserData(user.InternalId, userData, cancellationToken); _repository.SaveAllUserData(user.InternalId, userData, cancellationToken);
} }
/// <summary> /// <summary>
@ -108,14 +107,14 @@ namespace Emby.Server.Implementations.Library
/// <returns></returns> /// <returns></returns>
public List<UserItemData> GetAllUserData(Guid userId) public List<UserItemData> GetAllUserData(Guid userId)
{ {
var user = _userManager().GetUserById(userId); var user = _userManager.GetUserById(userId);
return Repository.GetAllUserData(user.InternalId); return _repository.GetAllUserData(user.InternalId);
} }
public UserItemData GetUserData(Guid userId, Guid itemId, List<string> keys) public UserItemData GetUserData(Guid userId, Guid itemId, List<string> keys)
{ {
var user = _userManager().GetUserById(userId); var user = _userManager.GetUserById(userId);
return GetUserData(user, itemId, keys); return GetUserData(user, itemId, keys);
} }
@ -131,7 +130,7 @@ namespace Emby.Server.Implementations.Library
private UserItemData GetUserDataInternal(long internalUserId, List<string> keys) private UserItemData GetUserDataInternal(long internalUserId, List<string> keys)
{ {
var userData = Repository.GetUserData(internalUserId, keys); var userData = _repository.GetUserData(internalUserId, keys);
if (userData != null) if (userData != null)
{ {

@ -44,22 +44,14 @@ namespace Emby.Server.Implementations.Library
{ {
private readonly object _policySyncLock = new object(); private readonly object _policySyncLock = new object();
private readonly object _configSyncLock = new object(); private readonly object _configSyncLock = new object();
/// <summary>
/// The logger.
/// </summary>
private readonly ILogger _logger;
/// <summary> private readonly ILogger _logger;
/// Gets the active user repository.
/// </summary>
/// <value>The user repository.</value>
private readonly IUserRepository _userRepository; private readonly IUserRepository _userRepository;
private readonly IXmlSerializer _xmlSerializer; private readonly IXmlSerializer _xmlSerializer;
private readonly IJsonSerializer _jsonSerializer; private readonly IJsonSerializer _jsonSerializer;
private readonly INetworkManager _networkManager; private readonly INetworkManager _networkManager;
private readonly IImageProcessor _imageProcessor;
private readonly Func<IImageProcessor> _imageProcessorFactory; private readonly Lazy<IDtoService> _dtoServiceFactory;
private readonly Func<IDtoService> _dtoServiceFactory;
private readonly IServerApplicationHost _appHost; private readonly IServerApplicationHost _appHost;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly ICryptoProvider _cryptoProvider; private readonly ICryptoProvider _cryptoProvider;
@ -74,13 +66,15 @@ namespace Emby.Server.Implementations.Library
private IPasswordResetProvider[] _passwordResetProviders; private IPasswordResetProvider[] _passwordResetProviders;
private DefaultPasswordResetProvider _defaultPasswordResetProvider; private DefaultPasswordResetProvider _defaultPasswordResetProvider;
private IDtoService DtoService => _dtoServiceFactory.Value;
public UserManager( public UserManager(
ILogger<UserManager> logger, ILogger<UserManager> logger,
IUserRepository userRepository, IUserRepository userRepository,
IXmlSerializer xmlSerializer, IXmlSerializer xmlSerializer,
INetworkManager networkManager, INetworkManager networkManager,
Func<IImageProcessor> imageProcessorFactory, IImageProcessor imageProcessor,
Func<IDtoService> dtoServiceFactory, Lazy<IDtoService> dtoServiceFactory,
IServerApplicationHost appHost, IServerApplicationHost appHost,
IJsonSerializer jsonSerializer, IJsonSerializer jsonSerializer,
IFileSystem fileSystem, IFileSystem fileSystem,
@ -90,7 +84,7 @@ namespace Emby.Server.Implementations.Library
_userRepository = userRepository; _userRepository = userRepository;
_xmlSerializer = xmlSerializer; _xmlSerializer = xmlSerializer;
_networkManager = networkManager; _networkManager = networkManager;
_imageProcessorFactory = imageProcessorFactory; _imageProcessor = imageProcessor;
_dtoServiceFactory = dtoServiceFactory; _dtoServiceFactory = dtoServiceFactory;
_appHost = appHost; _appHost = appHost;
_jsonSerializer = jsonSerializer; _jsonSerializer = jsonSerializer;
@ -605,7 +599,7 @@ namespace Emby.Server.Implementations.Library
try try
{ {
_dtoServiceFactory().AttachPrimaryImageAspectRatio(dto, user); DtoService.AttachPrimaryImageAspectRatio(dto, user);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -630,7 +624,7 @@ namespace Emby.Server.Implementations.Library
{ {
try try
{ {
return _imageProcessorFactory().GetImageCacheTag(item, image); return _imageProcessor.GetImageCacheTag(item, image);
} }
catch (Exception ex) catch (Exception ex)
{ {

@ -28,7 +28,6 @@ namespace Emby.Server.Implementations.LiveTv
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IImageProcessor _imageProcessor; private readonly IImageProcessor _imageProcessor;
private readonly IDtoService _dtoService; private readonly IDtoService _dtoService;
private readonly IApplicationHost _appHost; private readonly IApplicationHost _appHost;
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;

@ -49,29 +49,24 @@ namespace Emby.Server.Implementations.LiveTv
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IItemRepository _itemRepo; private readonly IItemRepository _itemRepo;
private readonly IUserManager _userManager; private readonly IUserManager _userManager;
private readonly IDtoService _dtoService;
private readonly IUserDataManager _userDataManager; private readonly IUserDataManager _userDataManager;
private readonly ILibraryManager _libraryManager; private readonly ILibraryManager _libraryManager;
private readonly ITaskManager _taskManager; private readonly ITaskManager _taskManager;
private readonly IJsonSerializer _jsonSerializer;
private readonly Func<IChannelManager> _channelManager;
private readonly IDtoService _dtoService;
private readonly ILocalizationManager _localization; private readonly ILocalizationManager _localization;
private readonly IJsonSerializer _jsonSerializer;
private readonly IFileSystem _fileSystem;
private readonly IChannelManager _channelManager;
private readonly LiveTvDtoService _tvDtoService; private readonly LiveTvDtoService _tvDtoService;
private ILiveTvService[] _services = Array.Empty<ILiveTvService>(); private ILiveTvService[] _services = Array.Empty<ILiveTvService>();
private ITunerHost[] _tunerHosts = Array.Empty<ITunerHost>(); private ITunerHost[] _tunerHosts = Array.Empty<ITunerHost>();
private IListingsProvider[] _listingProviders = Array.Empty<IListingsProvider>(); private IListingsProvider[] _listingProviders = Array.Empty<IListingsProvider>();
private readonly IFileSystem _fileSystem;
public LiveTvManager( public LiveTvManager(
IServerApplicationHost appHost,
IServerConfigurationManager config, IServerConfigurationManager config,
ILoggerFactory loggerFactory, ILogger<LiveTvManager> logger,
IItemRepository itemRepo, IItemRepository itemRepo,
IImageProcessor imageProcessor,
IUserDataManager userDataManager, IUserDataManager userDataManager,
IDtoService dtoService, IDtoService dtoService,
IUserManager userManager, IUserManager userManager,
@ -80,10 +75,11 @@ namespace Emby.Server.Implementations.LiveTv
ILocalizationManager localization, ILocalizationManager localization,
IJsonSerializer jsonSerializer, IJsonSerializer jsonSerializer,
IFileSystem fileSystem, IFileSystem fileSystem,
Func<IChannelManager> channelManager) IChannelManager channelManager,
LiveTvDtoService liveTvDtoService)
{ {
_config = config; _config = config;
_logger = loggerFactory.CreateLogger(nameof(LiveTvManager)); _logger = logger;
_itemRepo = itemRepo; _itemRepo = itemRepo;
_userManager = userManager; _userManager = userManager;
_libraryManager = libraryManager; _libraryManager = libraryManager;
@ -94,8 +90,7 @@ namespace Emby.Server.Implementations.LiveTv
_dtoService = dtoService; _dtoService = dtoService;
_userDataManager = userDataManager; _userDataManager = userDataManager;
_channelManager = channelManager; _channelManager = channelManager;
_tvDtoService = liveTvDtoService;
_tvDtoService = new LiveTvDtoService(dtoService, imageProcessor, loggerFactory.CreateLogger<LiveTvDtoService>(), appHost, _libraryManager);
} }
public event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCancelled; public event EventHandler<GenericEventArgs<TimerEventInfo>> SeriesTimerCancelled;
@ -2496,7 +2491,7 @@ namespace Emby.Server.Implementations.LiveTv
.OrderBy(i => i.SortName) .OrderBy(i => i.SortName)
.ToList(); .ToList();
folders.AddRange(_channelManager().GetChannelsInternal(new MediaBrowser.Model.Channels.ChannelQuery folders.AddRange(_channelManager.GetChannelsInternal(new MediaBrowser.Model.Channels.ChannelQuery
{ {
UserId = user.Id, UserId = user.Id,
IsRecordingsFolder = true, IsRecordingsFolder = true,

@ -23,9 +23,6 @@ namespace Emby.Server.Implementations.Localization
private static readonly Assembly _assembly = typeof(LocalizationManager).Assembly; private static readonly Assembly _assembly = typeof(LocalizationManager).Assembly;
private static readonly string[] _unratedValues = { "n/a", "unrated", "not rated" }; private static readonly string[] _unratedValues = { "n/a", "unrated", "not rated" };
/// <summary>
/// The _configuration manager.
/// </summary>
private readonly IServerConfigurationManager _configurationManager; private readonly IServerConfigurationManager _configurationManager;
private readonly IJsonSerializer _jsonSerializer; private readonly IJsonSerializer _jsonSerializer;
private readonly ILogger _logger; private readonly ILogger _logger;

@ -32,22 +32,8 @@ namespace Emby.Server.Implementations.ScheduledTasks
private readonly ConcurrentQueue<Tuple<Type, TaskOptions>> _taskQueue = private readonly ConcurrentQueue<Tuple<Type, TaskOptions>> _taskQueue =
new ConcurrentQueue<Tuple<Type, TaskOptions>>(); new ConcurrentQueue<Tuple<Type, TaskOptions>>();
/// <summary>
/// Gets or sets the json serializer.
/// </summary>
/// <value>The json serializer.</value>
private readonly IJsonSerializer _jsonSerializer; private readonly IJsonSerializer _jsonSerializer;
/// <summary>
/// Gets or sets the application paths.
/// </summary>
/// <value>The application paths.</value>
private readonly IApplicationPaths _applicationPaths; private readonly IApplicationPaths _applicationPaths;
/// <summary>
/// Gets the logger.
/// </summary>
/// <value>The logger.</value>
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
@ -56,17 +42,17 @@ namespace Emby.Server.Implementations.ScheduledTasks
/// </summary> /// </summary>
/// <param name="applicationPaths">The application paths.</param> /// <param name="applicationPaths">The application paths.</param>
/// <param name="jsonSerializer">The json serializer.</param> /// <param name="jsonSerializer">The json serializer.</param>
/// <param name="loggerFactory">The logger factory.</param> /// <param name="logger">The logger.</param>
/// <param name="fileSystem">The filesystem manager.</param> /// <param name="fileSystem">The filesystem manager.</param>
public TaskManager( public TaskManager(
IApplicationPaths applicationPaths, IApplicationPaths applicationPaths,
IJsonSerializer jsonSerializer, IJsonSerializer jsonSerializer,
ILoggerFactory loggerFactory, ILogger<TaskManager> logger,
IFileSystem fileSystem) IFileSystem fileSystem)
{ {
_applicationPaths = applicationPaths; _applicationPaths = applicationPaths;
_jsonSerializer = jsonSerializer; _jsonSerializer = jsonSerializer;
_logger = loggerFactory.CreateLogger(nameof(TaskManager)); _logger = logger;
_fileSystem = fileSystem; _fileSystem = fileSystem;
ScheduledTasks = Array.Empty<IScheduledTaskWorker>(); ScheduledTasks = Array.Empty<IScheduledTaskWorker>();

@ -15,8 +15,8 @@ namespace Emby.Server.Implementations.Security
{ {
public class AuthenticationRepository : BaseSqliteRepository, IAuthenticationRepository public class AuthenticationRepository : BaseSqliteRepository, IAuthenticationRepository
{ {
public AuthenticationRepository(ILoggerFactory loggerFactory, IServerConfigurationManager config) public AuthenticationRepository(ILogger<AuthenticationRepository> logger, IServerConfigurationManager config)
: base(loggerFactory.CreateLogger(nameof(AuthenticationRepository))) : base(logger)
{ {
DbFilePath = Path.Combine(config.ApplicationPaths.DataPath, "authentication.db"); DbFilePath = Path.Combine(config.ApplicationPaths.DataPath, "authentication.db");
} }

@ -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)

@ -1,9 +1,13 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using Emby.Drawing;
using Emby.Server.Implementations; using Emby.Server.Implementations;
using Jellyfin.Drawing.Skia;
using MediaBrowser.Common.Net; using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Drawing;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace Jellyfin.Server namespace Jellyfin.Server
@ -20,27 +24,40 @@ 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)
{ {
} }
/// <inheritdoc /> /// <inheritdoc/>
public override bool CanSelfRestart => StartupOptions.RestartPath != null; protected override void RegisterServices(IServiceCollection serviceCollection)
{
// Register an image encoder
bool useSkiaEncoder = SkiaEncoder.IsNativeLibAvailable();
Type imageEncoderType = useSkiaEncoder
? typeof(SkiaEncoder)
: typeof(NullImageEncoder);
serviceCollection.AddSingleton(typeof(IImageEncoder), imageEncoderType);
// Log a warning if the Skia encoder could not be used
if (!useSkiaEncoder)
{
Logger.LogWarning($"Skia not available. Will fallback to {nameof(NullImageEncoder)}.");
}
base.RegisterServices(serviceCollection);
}
/// <inheritdoc /> /// <inheritdoc />
protected override void RestartInternal() => Program.Restart(); protected override void RestartInternal() => Program.Restart();

@ -184,7 +184,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
@ -204,14 +203,13 @@ namespace Jellyfin.Server
} }
ServiceCollection serviceCollection = new ServiceCollection(); ServiceCollection serviceCollection = new ServiceCollection();
await appHost.InitAsync(serviceCollection, startupConfig).ConfigureAwait(false); appHost.Init(serviceCollection);
var webHost = CreateWebHostBuilder(appHost, serviceCollection, options, startupConfig, appPaths).Build(); var webHost = CreateWebHostBuilder(appHost, serviceCollection, options, startupConfig, appPaths).Build();
// Re-use the web host service provider in the app host since ASP.NET doesn't allow a custom service collection. // Re-use the web host service provider in the app host since ASP.NET doesn't allow a custom service collection.
appHost.ServiceProvider = webHost.Services; appHost.ServiceProvider = webHost.Services;
appHost.InitializeServices(); await appHost.InitializeServices().ConfigureAwait(false);
appHost.FindParts();
Migrations.MigrationRunner.Run(appHost, _loggerFactory); Migrations.MigrationRunner.Run(appHost, _loggerFactory);
try try
@ -571,25 +569,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");

@ -332,7 +332,8 @@ namespace MediaBrowser.Api.Images
var fileInfo = _fileSystem.GetFileInfo(info.Path); var fileInfo = _fileSystem.GetFileInfo(info.Path);
length = fileInfo.Length; length = fileInfo.Length;
ImageDimensions size = _imageProcessor.GetImageDimensions(item, info, true); ImageDimensions size = _imageProcessor.GetImageDimensions(item, info);
_libraryManager.UpdateImages(item);
width = size.Width; width = size.Width;
height = size.Height; height = size.Height;
@ -606,6 +607,12 @@ namespace MediaBrowser.Api.Images
IDictionary<string, string> headers, IDictionary<string, string> headers,
bool isHeadRequest) bool isHeadRequest)
{ {
if (!image.IsLocalFile)
{
item ??= _libraryManager.GetItemById(itemId);
image = await _libraryManager.ConvertImageToLocal(item, image, request.Index ?? 0).ConfigureAwait(false);
}
var options = new ImageProcessingOptions var options = new ImageProcessingOptions
{ {
CropWhiteSpace = cropwhitespace, CropWhiteSpace = cropwhitespace,

@ -2,8 +2,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Plugins;
using MediaBrowser.Model.Updates;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
namespace MediaBrowser.Common namespace MediaBrowser.Common
@ -119,9 +117,7 @@ namespace MediaBrowser.Common
/// Initializes this instance. /// Initializes this instance.
/// </summary> /// </summary>
/// <param name="serviceCollection">The service collection.</param> /// <param name="serviceCollection">The service collection.</param>
/// <param name="startupConfig">The configuration to use for initialization.</param> void Init(IServiceCollection serviceCollection);
/// <returns>A task.</returns>
Task InitAsync(IServiceCollection serviceCollection, IConfiguration startupConfig);
/// <summary> /// <summary>
/// Creates the instance. /// Creates the instance.

@ -40,15 +40,6 @@ namespace MediaBrowser.Controller.Drawing
/// <returns>ImageDimensions</returns> /// <returns>ImageDimensions</returns>
ImageDimensions GetImageDimensions(BaseItem item, ItemImageInfo info); ImageDimensions GetImageDimensions(BaseItem item, ItemImageInfo info);
/// <summary>
/// Gets the dimensions of the image.
/// </summary>
/// <param name="item">The base item.</param>
/// <param name="info">The information.</param>
/// <param name="updateItem">Whether or not the item info should be updated.</param>
/// <returns>ImageDimensions</returns>
ImageDimensions GetImageDimensions(BaseItem item, ItemImageInfo info, bool updateItem);
/// <summary> /// <summary>
/// Gets the image cache tag. /// Gets the image cache tag.
/// </summary> /// </summary>

@ -459,7 +459,7 @@ namespace MediaBrowser.Controller.MediaEncoding
{ {
var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions); var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions);
var outputVideoCodec = GetVideoEncoder(state, encodingOptions); var outputVideoCodec = GetVideoEncoder(state, encodingOptions);
var hasTextSubs = state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode; var hasTextSubs = state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode;
if (!hasTextSubs) if (!hasTextSubs)

@ -19,7 +19,6 @@ using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.System; using MediaBrowser.Model.System;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Diagnostics; using System.Diagnostics;
@ -39,8 +38,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
private readonly IServerConfigurationManager _configurationManager; private readonly IServerConfigurationManager _configurationManager;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly ILocalizationManager _localization; private readonly ILocalizationManager _localization;
private readonly Func<ISubtitleEncoder> _subtitleEncoder; private readonly Lazy<EncodingHelper> _encodingHelperFactory;
private readonly IConfiguration _configuration;
private readonly string _startupOptionFFmpegPath; private readonly string _startupOptionFFmpegPath;
private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(2, 2); private readonly SemaphoreSlim _thumbnailResourcePool = new SemaphoreSlim(2, 2);
@ -48,8 +46,6 @@ namespace MediaBrowser.MediaEncoding.Encoder
private readonly object _runningProcessesLock = new object(); private readonly object _runningProcessesLock = new object();
private readonly List<ProcessWrapper> _runningProcesses = new List<ProcessWrapper>(); private readonly List<ProcessWrapper> _runningProcesses = new List<ProcessWrapper>();
private EncodingHelper _encodingHelper;
private string _ffmpegPath; private string _ffmpegPath;
private string _ffprobePath; private string _ffprobePath;
@ -58,23 +54,18 @@ namespace MediaBrowser.MediaEncoding.Encoder
IServerConfigurationManager configurationManager, IServerConfigurationManager configurationManager,
IFileSystem fileSystem, IFileSystem fileSystem,
ILocalizationManager localization, ILocalizationManager localization,
Func<ISubtitleEncoder> subtitleEncoder, Lazy<EncodingHelper> encodingHelperFactory,
IConfiguration configuration,
string startupOptionsFFmpegPath) string startupOptionsFFmpegPath)
{ {
_logger = logger; _logger = logger;
_configurationManager = configurationManager; _configurationManager = configurationManager;
_fileSystem = fileSystem; _fileSystem = fileSystem;
_localization = localization; _localization = localization;
_encodingHelperFactory = encodingHelperFactory;
_startupOptionFFmpegPath = startupOptionsFFmpegPath; _startupOptionFFmpegPath = startupOptionsFFmpegPath;
_subtitleEncoder = subtitleEncoder;
_configuration = configuration;
} }
private EncodingHelper EncodingHelper private EncodingHelper EncodingHelper => _encodingHelperFactory.Value;
=> LazyInitializer.EnsureInitialized(
ref _encodingHelper,
() => new EncodingHelper(this, _fileSystem, _subtitleEncoder(), _configuration));
/// <inheritdoc /> /// <inheritdoc />
public string EncoderPath => _ffmpegPath; public string EncoderPath => _ffmpegPath;

@ -36,60 +36,51 @@ namespace MediaBrowser.Providers.Manager
/// </summary> /// </summary>
public class ProviderManager : IProviderManager, IDisposable public class ProviderManager : IProviderManager, IDisposable
{ {
/// <summary>
/// The _logger
/// </summary>
private readonly ILogger _logger; private readonly ILogger _logger;
/// <summary>
/// The _HTTP client
/// </summary>
private readonly IHttpClient _httpClient; private readonly IHttpClient _httpClient;
/// <summary>
/// The _directory watchers
/// </summary>
private readonly ILibraryMonitor _libraryMonitor; private readonly ILibraryMonitor _libraryMonitor;
private readonly IFileSystem _fileSystem;
/// <summary> private readonly IServerApplicationPaths _appPaths;
/// Gets or sets the configuration manager. private readonly IJsonSerializer _json;
/// </summary> private readonly ILibraryManager _libraryManager;
/// <value>The configuration manager.</value> private readonly ISubtitleManager _subtitleManager;
private IServerConfigurationManager ConfigurationManager { get; set; } private readonly IServerConfigurationManager _configurationManager;
private IImageProvider[] ImageProviders { get; set; } private IImageProvider[] ImageProviders { get; set; }
private readonly IFileSystem _fileSystem;
private IMetadataService[] _metadataServices = { }; private IMetadataService[] _metadataServices = { };
private IMetadataProvider[] _metadataProviders = { }; private IMetadataProvider[] _metadataProviders = { };
private IEnumerable<IMetadataSaver> _savers; private IEnumerable<IMetadataSaver> _savers;
private readonly IServerApplicationPaths _appPaths;
private readonly IJsonSerializer _json;
private IExternalId[] _externalIds; private IExternalId[] _externalIds;
private readonly Func<ILibraryManager> _libraryManagerFactory;
private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource(); private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource();
public event EventHandler<GenericEventArgs<BaseItem>> RefreshStarted; public event EventHandler<GenericEventArgs<BaseItem>> RefreshStarted;
public event EventHandler<GenericEventArgs<BaseItem>> RefreshCompleted; public event EventHandler<GenericEventArgs<BaseItem>> RefreshCompleted;
public event EventHandler<GenericEventArgs<Tuple<BaseItem, double>>> RefreshProgress; public event EventHandler<GenericEventArgs<Tuple<BaseItem, double>>> RefreshProgress;
private ISubtitleManager _subtitleManager;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ProviderManager" /> class. /// Initializes a new instance of the <see cref="ProviderManager" /> class.
/// </summary> /// </summary>
public ProviderManager(IHttpClient httpClient, ISubtitleManager subtitleManager, IServerConfigurationManager configurationManager, ILibraryMonitor libraryMonitor, ILoggerFactory loggerFactory, IFileSystem fileSystem, IServerApplicationPaths appPaths, Func<ILibraryManager> libraryManagerFactory, IJsonSerializer json) public ProviderManager(
IHttpClient httpClient,
ISubtitleManager subtitleManager,
IServerConfigurationManager configurationManager,
ILibraryMonitor libraryMonitor,
ILogger<ProviderManager> logger,
IFileSystem fileSystem,
IServerApplicationPaths appPaths,
ILibraryManager libraryManager,
IJsonSerializer json)
{ {
_logger = loggerFactory.CreateLogger("ProviderManager"); _logger = logger;
_httpClient = httpClient; _httpClient = httpClient;
ConfigurationManager = configurationManager; _configurationManager = configurationManager;
_libraryMonitor = libraryMonitor; _libraryMonitor = libraryMonitor;
_fileSystem = fileSystem; _fileSystem = fileSystem;
_appPaths = appPaths; _appPaths = appPaths;
_libraryManagerFactory = libraryManagerFactory; _libraryManager = libraryManager;
_json = json; _json = json;
_subtitleManager = subtitleManager; _subtitleManager = subtitleManager;
} }
@ -176,7 +167,7 @@ namespace MediaBrowser.Providers.Manager
public Task SaveImage(BaseItem item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken) public Task SaveImage(BaseItem item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken)
{ {
return new ImageSaver(ConfigurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, source, mimeType, type, imageIndex, cancellationToken); return new ImageSaver(_configurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, source, mimeType, type, imageIndex, cancellationToken);
} }
public Task SaveImage(BaseItem item, string source, string mimeType, ImageType type, int? imageIndex, bool? saveLocallyWithMedia, CancellationToken cancellationToken) public Task SaveImage(BaseItem item, string source, string mimeType, ImageType type, int? imageIndex, bool? saveLocallyWithMedia, CancellationToken cancellationToken)
@ -188,7 +179,7 @@ namespace MediaBrowser.Providers.Manager
var fileStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, true); var fileStream = new FileStream(source, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, true);
return new ImageSaver(ConfigurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, fileStream, mimeType, type, imageIndex, saveLocallyWithMedia, cancellationToken); return new ImageSaver(_configurationManager, _libraryMonitor, _fileSystem, _logger).SaveImage(item, fileStream, mimeType, type, imageIndex, saveLocallyWithMedia, cancellationToken);
} }
public async Task<IEnumerable<RemoteImageInfo>> GetAvailableRemoteImages(BaseItem item, RemoteImageQuery query, CancellationToken cancellationToken) public async Task<IEnumerable<RemoteImageInfo>> GetAvailableRemoteImages(BaseItem item, RemoteImageQuery query, CancellationToken cancellationToken)
@ -273,7 +264,7 @@ namespace MediaBrowser.Providers.Manager
public IEnumerable<IImageProvider> GetImageProviders(BaseItem item, ImageRefreshOptions refreshOptions) public IEnumerable<IImageProvider> GetImageProviders(BaseItem item, ImageRefreshOptions refreshOptions)
{ {
return GetImageProviders(item, _libraryManagerFactory().GetLibraryOptions(item), GetMetadataOptions(item), refreshOptions, false); return GetImageProviders(item, _libraryManager.GetLibraryOptions(item), GetMetadataOptions(item), refreshOptions, false);
} }
private IEnumerable<IImageProvider> GetImageProviders(BaseItem item, LibraryOptions libraryOptions, MetadataOptions options, ImageRefreshOptions refreshOptions, bool includeDisabled) private IEnumerable<IImageProvider> GetImageProviders(BaseItem item, LibraryOptions libraryOptions, MetadataOptions options, ImageRefreshOptions refreshOptions, bool includeDisabled)
@ -328,7 +319,7 @@ namespace MediaBrowser.Providers.Manager
private IEnumerable<IRemoteImageProvider> GetRemoteImageProviders(BaseItem item, bool includeDisabled) private IEnumerable<IRemoteImageProvider> GetRemoteImageProviders(BaseItem item, bool includeDisabled)
{ {
var options = GetMetadataOptions(item); var options = GetMetadataOptions(item);
var libraryOptions = _libraryManagerFactory().GetLibraryOptions(item); var libraryOptions = _libraryManager.GetLibraryOptions(item);
return GetImageProviders(item, libraryOptions, options, return GetImageProviders(item, libraryOptions, options,
new ImageRefreshOptions( new ImageRefreshOptions(
@ -593,7 +584,7 @@ namespace MediaBrowser.Providers.Manager
{ {
var type = item.GetType().Name; var type = item.GetType().Name;
return ConfigurationManager.Configuration.MetadataOptions return _configurationManager.Configuration.MetadataOptions
.FirstOrDefault(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase)) ?? .FirstOrDefault(i => string.Equals(i.ItemType, type, StringComparison.OrdinalIgnoreCase)) ??
new MetadataOptions(); new MetadataOptions();
} }
@ -623,7 +614,7 @@ namespace MediaBrowser.Providers.Manager
/// <returns>Task.</returns> /// <returns>Task.</returns>
private void SaveMetadata(BaseItem item, ItemUpdateType updateType, IEnumerable<IMetadataSaver> savers) private void SaveMetadata(BaseItem item, ItemUpdateType updateType, IEnumerable<IMetadataSaver> savers)
{ {
var libraryOptions = _libraryManagerFactory().GetLibraryOptions(item); var libraryOptions = _libraryManager.GetLibraryOptions(item);
foreach (var saver in savers.Where(i => IsSaverEnabledForItem(i, item, libraryOptions, updateType, false))) foreach (var saver in savers.Where(i => IsSaverEnabledForItem(i, item, libraryOptions, updateType, false)))
{ {
@ -743,7 +734,7 @@ namespace MediaBrowser.Providers.Manager
if (!searchInfo.ItemId.Equals(Guid.Empty)) if (!searchInfo.ItemId.Equals(Guid.Empty))
{ {
referenceItem = _libraryManagerFactory().GetItemById(searchInfo.ItemId); referenceItem = _libraryManager.GetItemById(searchInfo.ItemId);
} }
return GetRemoteSearchResults<TItemType, TLookupType>(searchInfo, referenceItem, cancellationToken); return GetRemoteSearchResults<TItemType, TLookupType>(searchInfo, referenceItem, cancellationToken);
@ -771,7 +762,7 @@ namespace MediaBrowser.Providers.Manager
} }
else else
{ {
libraryOptions = _libraryManagerFactory().GetLibraryOptions(referenceItem); libraryOptions = _libraryManager.GetLibraryOptions(referenceItem);
} }
var options = GetMetadataOptions(referenceItem); var options = GetMetadataOptions(referenceItem);
@ -786,11 +777,11 @@ namespace MediaBrowser.Providers.Manager
if (string.IsNullOrWhiteSpace(searchInfo.SearchInfo.MetadataLanguage)) if (string.IsNullOrWhiteSpace(searchInfo.SearchInfo.MetadataLanguage))
{ {
searchInfo.SearchInfo.MetadataLanguage = ConfigurationManager.Configuration.PreferredMetadataLanguage; searchInfo.SearchInfo.MetadataLanguage = _configurationManager.Configuration.PreferredMetadataLanguage;
} }
if (string.IsNullOrWhiteSpace(searchInfo.SearchInfo.MetadataCountryCode)) if (string.IsNullOrWhiteSpace(searchInfo.SearchInfo.MetadataCountryCode))
{ {
searchInfo.SearchInfo.MetadataCountryCode = ConfigurationManager.Configuration.MetadataCountryCode; searchInfo.SearchInfo.MetadataCountryCode = _configurationManager.Configuration.MetadataCountryCode;
} }
var resultList = new List<RemoteSearchResult>(); var resultList = new List<RemoteSearchResult>();
@ -967,7 +958,7 @@ namespace MediaBrowser.Providers.Manager
public void OnRefreshProgress(BaseItem item, double progress) public void OnRefreshProgress(BaseItem item, double progress)
{ {
var id = item.Id; var id = item.Id;
_logger.LogInformation("OnRefreshProgress {0} {1}", id.ToString("N", CultureInfo.InvariantCulture), progress); _logger.LogDebug("OnRefreshProgress {0} {1}", id.ToString("N", CultureInfo.InvariantCulture), progress);
// TODO: Need to hunt down the conditions for this happening // TODO: Need to hunt down the conditions for this happening
_activeRefreshes.AddOrUpdate( _activeRefreshes.AddOrUpdate(
@ -1010,7 +1001,7 @@ namespace MediaBrowser.Providers.Manager
private async Task StartProcessingRefreshQueue() private async Task StartProcessingRefreshQueue()
{ {
var libraryManager = _libraryManagerFactory(); var libraryManager = _libraryManager;
if (_disposed) if (_disposed)
{ {
@ -1088,7 +1079,7 @@ namespace MediaBrowser.Providers.Manager
private async Task RefreshArtist(MusicArtist item, MetadataRefreshOptions options, CancellationToken cancellationToken) private async Task RefreshArtist(MusicArtist item, MetadataRefreshOptions options, CancellationToken cancellationToken)
{ {
var albums = _libraryManagerFactory() var albums = _libraryManager
.GetItemList(new InternalItemsQuery .GetItemList(new InternalItemsQuery
{ {
IncludeItemTypes = new[] { nameof(MusicAlbum) }, IncludeItemTypes = new[] { nameof(MusicAlbum) },

@ -25,22 +25,22 @@ namespace MediaBrowser.Providers.Subtitles
{ {
public class SubtitleManager : ISubtitleManager public class SubtitleManager : ISubtitleManager
{ {
private ISubtitleProvider[] _subtitleProviders;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly ILibraryMonitor _monitor; private readonly ILibraryMonitor _monitor;
private readonly IMediaSourceManager _mediaSourceManager; private readonly IMediaSourceManager _mediaSourceManager;
private readonly ILocalizationManager _localization;
private ILocalizationManager _localization; private ISubtitleProvider[] _subtitleProviders;
public SubtitleManager( public SubtitleManager(
ILoggerFactory loggerFactory, ILogger<SubtitleManager> logger,
IFileSystem fileSystem, IFileSystem fileSystem,
ILibraryMonitor monitor, ILibraryMonitor monitor,
IMediaSourceManager mediaSourceManager, IMediaSourceManager mediaSourceManager,
ILocalizationManager localizationManager) ILocalizationManager localizationManager)
{ {
_logger = loggerFactory.CreateLogger(nameof(SubtitleManager)); _logger = logger;
_fileSystem = fileSystem; _fileSystem = fileSystem;
_monitor = monitor; _monitor = monitor;
_mediaSourceManager = mediaSourceManager; _mediaSourceManager = mediaSourceManager;

Loading…
Cancel
Save