From 07cebbeae2bbbe63f0f97428e73e419220ab5804 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 17:12:24 -0400 Subject: Register and construct IImageProcessor, SqliteItemRepository and IImageEncoder correctly --- Jellyfin.Server/CoreAppHost.cs | 3 --- 1 file changed, 3 deletions(-) (limited to 'Jellyfin.Server/CoreAppHost.cs') diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index 1d5313c13e..b35200e757 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -20,21 +20,18 @@ namespace Jellyfin.Server /// The to be used by the . /// The to be used by the . /// The to be used by the . - /// The to be used by the . /// The to be used by the . public CoreAppHost( ServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, StartupOptions options, IFileSystem fileSystem, - IImageEncoder imageEncoder, INetworkManager networkManager) : base( applicationPaths, loggerFactory, options, fileSystem, - imageEncoder, networkManager) { } -- cgit v1.2.3 From 735d6c8ad531904c24650d88dd07ef3e57ded46a Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sat, 4 Apr 2020 23:18:11 -0400 Subject: Convert properties in ApplicationHost to private readonly fields, where possible --- Emby.Server.Implementations/ApplicationHost.cs | 67 +++++++++------------- .../Data/SqliteItemRepository.cs | 2 +- Jellyfin.Server/CoreAppHost.cs | 3 - 3 files changed, 27 insertions(+), 45 deletions(-) (limited to 'Jellyfin.Server/CoreAppHost.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 0620469c0f..06b6fec555 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -119,17 +119,21 @@ namespace Emby.Server.Implementations /// public abstract class ApplicationHost : IServerApplicationHost, IDisposable { - private SqliteUserRepository _userRepository; + private readonly IFileSystem _fileSystemManager; + private readonly INetworkManager _networkManager; + private readonly IXmlSerializer _xmlSerializer; + private readonly IStartupOptions _startupOptions; + private IMediaEncoder _mediaEncoder; private ISessionManager _sessionManager; private IHttpServer _httpServer; private IHttpClient _httpClient; + private IInstallationManager _installationManager; /// /// Gets a value indicating whether this instance can self restart. /// - /// true if this instance can self restart; otherwise, false. - public abstract bool CanSelfRestart { get; } + public bool CanSelfRestart => _startupOptions.RestartPath != null; public virtual bool CanLaunchWebBrowser { @@ -140,7 +144,7 @@ namespace Emby.Server.Implementations return false; } - if (StartupOptions.IsService) + if (_startupOptions.IsService) { return false; } @@ -210,8 +214,6 @@ namespace Emby.Server.Implementations /// The configuration manager. protected IConfigurationManager ConfigurationManager { get; set; } - public IFileSystem FileSystemManager { get; set; } - /// public PackageVersionClass SystemUpdateLevel { @@ -246,18 +248,6 @@ namespace Emby.Server.Implementations /// The server configuration manager. public IServerConfigurationManager ServerConfigurationManager => (IServerConfigurationManager)ConfigurationManager; - /// - /// Gets the installation manager. - /// - /// The installation manager. - protected IInstallationManager InstallationManager { get; private set; } - - public IStartupOptions StartupOptions { get; } - - protected readonly IXmlSerializer XmlSerializer; - - protected INetworkManager NetworkManager { get; set; } - /// /// Initializes a new instance of the class. /// @@ -268,24 +258,24 @@ namespace Emby.Server.Implementations IFileSystem fileSystem, INetworkManager networkManager) { - XmlSerializer = new MyXmlSerializer(); + _xmlSerializer = new MyXmlSerializer(); - NetworkManager = networkManager; + _networkManager = networkManager; networkManager.LocalSubnetsFn = GetConfiguredLocalSubnets; ApplicationPaths = applicationPaths; LoggerFactory = loggerFactory; - FileSystemManager = fileSystem; + _fileSystemManager = fileSystem; - ConfigurationManager = new ServerConfigurationManager(ApplicationPaths, LoggerFactory, XmlSerializer, FileSystemManager); + ConfigurationManager = new ServerConfigurationManager(ApplicationPaths, LoggerFactory, _xmlSerializer, _fileSystemManager); Logger = LoggerFactory.CreateLogger("App"); - StartupOptions = options; + _startupOptions = options; fileSystem.AddShortcutHandler(new MbLinkShortcutHandler(fileSystem)); - NetworkManager.NetworkChanged += OnNetworkChanged; + _networkManager.NetworkChanged += OnNetworkChanged; CertificateInfo = new CertificateInfo { @@ -575,18 +565,18 @@ namespace Emby.Server.Implementations return Logger; }); - serviceCollection.AddSingleton(FileSystemManager); + serviceCollection.AddSingleton(_fileSystemManager); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(NetworkManager); + serviceCollection.AddSingleton(_networkManager); serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(XmlSerializer); + serviceCollection.AddSingleton(_xmlSerializer); serviceCollection.AddSingleton(); @@ -636,7 +626,7 @@ namespace Emby.Server.Implementations provider.GetRequiredService(), provider.GetRequiredService, provider.GetRequiredService(), - StartupOptions.FFmpegPath)); + _startupOptions.FFmpegPath)); // TODO: Refactor to eliminate the circular dependencies here so that Lazy isn't required serviceCollection.AddTransient(provider => new Lazy(provider.GetRequiredService)); @@ -736,6 +726,8 @@ namespace Emby.Server.Implementations var userDataRepo = (SqliteUserDataRepository)Resolve(); ((SqliteItemRepository)Resolve()).Initialize(userDataRepo, userManager); + Resolve().PluginInstalled += PluginInstalled; + FindParts(); } @@ -818,7 +810,7 @@ namespace Emby.Server.Implementations BaseItem.LocalizationManager = Resolve(); BaseItem.ItemRepository = Resolve(); User.UserManager = Resolve(); - BaseItem.FileSystem = FileSystemManager; + BaseItem.FileSystem = _fileSystemManager; BaseItem.UserDataManager = Resolve(); BaseItem.ChannelManager = Resolve(); Video.LiveTvManager = Resolve(); @@ -826,7 +818,7 @@ namespace Emby.Server.Implementations UserView.TVSeriesManager = Resolve(); UserView.CollectionManager = Resolve(); BaseItem.MediaSourceManager = Resolve(); - CollectionFolder.XmlSerializer = XmlSerializer; + CollectionFolder.XmlSerializer = _xmlSerializer; CollectionFolder.JsonSerializer = Resolve(); CollectionFolder.ApplicationHost = this; AuthenticatedAttribute.AuthService = Resolve(); @@ -872,9 +864,6 @@ namespace Emby.Server.Implementations /// private void FindParts() { - InstallationManager = ServiceProvider.GetService(); - InstallationManager.PluginInstalled += PluginInstalled; - if (!ServerConfigurationManager.Configuration.IsPortAuthorized) { ServerConfigurationManager.Configuration.IsPortAuthorized = true; @@ -1210,7 +1199,7 @@ namespace Emby.Server.Implementations IsShuttingDown = IsShuttingDown, Version = ApplicationVersionString, WebSocketPortNumber = HttpPort, - CompletedInstallations = InstallationManager.CompletedInstallations.ToArray(), + CompletedInstallations = _installationManager.CompletedInstallations.ToArray(), Id = SystemId, ProgramDataPath = ApplicationPaths.ProgramDataPath, WebPath = ApplicationPaths.WebPath, @@ -1233,12 +1222,12 @@ namespace Emby.Server.Implementations EncoderLocation = _mediaEncoder.EncoderLocation, SystemArchitecture = RuntimeInformation.OSArchitecture, SystemUpdateLevel = SystemUpdateLevel, - PackageName = StartupOptions.PackageName + PackageName = _startupOptions.PackageName }; } public IEnumerable GetWakeOnLanInfo() - => NetworkManager.GetMacAddresses() + => _networkManager.GetMacAddresses() .Select(i => new WakeOnLanInfo(i)) .ToList(); @@ -1350,7 +1339,7 @@ namespace Emby.Server.Implementations if (addresses.Count == 0) { - addresses.AddRange(NetworkManager.GetLocalIpAddresses(ServerConfigurationManager.Configuration.IgnoreVirtualInterfaces)); + addresses.AddRange(_networkManager.GetLocalIpAddresses(ServerConfigurationManager.Configuration.IgnoreVirtualInterfaces)); } var resultList = new List(); @@ -1594,12 +1583,8 @@ namespace Emby.Server.Implementations Logger.LogError(ex, "Error disposing {Type}", part.GetType().Name); } } - - _userRepository?.Dispose(); } - _userRepository = null; - _disposed = true; } } diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 227f1a5e7e..8db4146cd3 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -42,7 +42,7 @@ namespace Emby.Server.Implementations.Data private readonly IServerConfigurationManager _config; private readonly IServerApplicationHost _appHost; private readonly ILocalizationManager _localization; - // TODO: Remove this dependency + // 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; diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index b35200e757..c3ac2ab411 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -36,9 +36,6 @@ namespace Jellyfin.Server { } - /// - public override bool CanSelfRestart => StartupOptions.RestartPath != null; - /// protected override void RestartInternal() => Program.Restart(); -- cgit v1.2.3 From f2760cb055ae6ee5971ca4a3ff342ecd7d829d99 Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Sun, 5 Apr 2020 10:03:53 -0400 Subject: Register IImageEncoder in Jellyfin.Server instead of Emby.Server.Implementations --- Emby.Server.Implementations/ApplicationHost.cs | 8 +------- .../Emby.Server.Implementations.csproj | 1 - Jellyfin.Server/CoreAppHost.cs | 14 ++++++++++++++ 3 files changed, 15 insertions(+), 8 deletions(-) (limited to 'Jellyfin.Server/CoreAppHost.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 06b6fec555..0bc47627a1 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -48,7 +48,6 @@ using Emby.Server.Implementations.Session; using Emby.Server.Implementations.SocketSharp; using Emby.Server.Implementations.TV; using Emby.Server.Implementations.Updates; -using Jellyfin.Drawing.Skia; using MediaBrowser.Api; using MediaBrowser.Common; using MediaBrowser.Common.Configuration; @@ -540,13 +539,8 @@ namespace Emby.Server.Implementations /// /// Registers services/resources with the service collection that will be available via DI. /// - protected void RegisterServices(IServiceCollection serviceCollection) + protected virtual void RegisterServices(IServiceCollection serviceCollection) { - var imageEncoderType = SkiaEncoder.IsNativeLibAvailable() - ? typeof(SkiaEncoder) - : typeof(NullImageEncoder); - serviceCollection.AddSingleton(typeof(IImageEncoder), imageEncoderType); - serviceCollection.AddSingleton(_startupOptions); serviceCollection.AddMemoryCache(); diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 6c20842c7f..d302d89843 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -4,7 +4,6 @@ - diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index c3ac2ab411..0769bf844e 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -1,9 +1,12 @@ using System.Collections.Generic; using System.Reflection; +using Emby.Drawing; using Emby.Server.Implementations; +using Jellyfin.Drawing.Skia; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Drawing; using MediaBrowser.Model.IO; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; namespace Jellyfin.Server @@ -36,6 +39,17 @@ namespace Jellyfin.Server { } + /// + protected override void RegisterServices(IServiceCollection serviceCollection) + { + var imageEncoderType = SkiaEncoder.IsNativeLibAvailable() + ? typeof(SkiaEncoder) + : typeof(NullImageEncoder); + serviceCollection.AddSingleton(typeof(IImageEncoder), imageEncoderType); + + base.RegisterServices(serviceCollection); + } + /// protected override void RestartInternal() => Program.Restart(); -- cgit v1.2.3 From ecf49caf0d1392b0f2aa83bce1d08a006463566d Mon Sep 17 00:00:00 2001 From: Mark Monteiro Date: Fri, 17 Apr 2020 10:24:46 -0400 Subject: Add back warning message when Skia encoder cannot be used --- Jellyfin.Server/CoreAppHost.cs | 11 ++++++++++- MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'Jellyfin.Server/CoreAppHost.cs') diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index 0769bf844e..f678e714c1 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Reflection; using Emby.Drawing; @@ -42,11 +43,19 @@ namespace Jellyfin.Server /// protected override void RegisterServices(IServiceCollection serviceCollection) { - var imageEncoderType = SkiaEncoder.IsNativeLibAvailable() + // 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); } diff --git a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs index 3552a45a23..5efb10d3a9 100644 --- a/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs +++ b/MediaBrowser.Controller/MediaEncoding/EncodingHelper.cs @@ -459,7 +459,7 @@ namespace MediaBrowser.Controller.MediaEncoding { var videoDecoder = GetHardwareAcceleratedVideoDecoder(state, encodingOptions); var outputVideoCodec = GetVideoEncoder(state, encodingOptions); - + var hasTextSubs = state.SubtitleStream != null && state.SubtitleStream.IsTextSubtitleStream && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode; if (!hasTextSubs) -- cgit v1.2.3 From b94afc597c4d51f67552c9ba2c25bdb8df6d8599 Mon Sep 17 00:00:00 2001 From: Patrick Barron Date: Thu, 14 May 2020 17:13:45 -0400 Subject: Address review comments --- Emby.Server.Implementations/ApplicationHost.cs | 11 --- .../Configuration/ServerConfigurationManager.cs | 6 -- .../Emby.Server.Implementations.csproj | 3 +- Jellyfin.Data/Entities/ActivityLog.cs | 83 +++++++++++----------- Jellyfin.Data/Jellyfin.Data.csproj | 6 +- .../Activity/ActivityManager.cs | 14 ++-- .../Jellyfin.Server.Implementations.csproj | 8 +++ Jellyfin.Server.Implementations/JellyfinDb.cs | 2 +- .../JellyfinDbProvider.cs | 2 +- .../20200502231229_InitialSchema.Designer.cs | 73 ------------------- .../Migrations/20200502231229_InitialSchema.cs | 46 ------------ .../20200514181226_AddActivityLog.Designer.cs | 72 +++++++++++++++++++ .../Migrations/20200514181226_AddActivityLog.cs | 46 ++++++++++++ .../Migrations/DesignTimeJellyfinDbFactory.cs | 7 +- .../Migrations/JellyfinDbModelSnapshot.cs | 4 +- Jellyfin.Server/CoreAppHost.cs | 14 ++++ Jellyfin.Server/Jellyfin.Server.csproj | 8 +-- MediaBrowser.Api/System/ActivityLogService.cs | 13 +++- MediaBrowser.Model/Activity/IActivityManager.cs | 3 +- .../Configuration/ServerConfiguration.cs | 2 - MediaBrowser.Model/Devices/DeviceOptions.cs | 9 +++ MediaBrowser.Model/Devices/DevicesOptions.cs | 23 ------ 22 files changed, 221 insertions(+), 234 deletions(-) delete mode 100644 Jellyfin.Server.Implementations/Migrations/20200502231229_InitialSchema.Designer.cs delete mode 100644 Jellyfin.Server.Implementations/Migrations/20200502231229_InitialSchema.cs create mode 100644 Jellyfin.Server.Implementations/Migrations/20200514181226_AddActivityLog.Designer.cs create mode 100644 Jellyfin.Server.Implementations/Migrations/20200514181226_AddActivityLog.cs create mode 100644 MediaBrowser.Model/Devices/DeviceOptions.cs delete mode 100644 MediaBrowser.Model/Devices/DevicesOptions.cs (limited to 'Jellyfin.Server/CoreAppHost.cs') diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 371b5a5b9b..8e5c3c9cf2 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -46,8 +46,6 @@ using Emby.Server.Implementations.Session; using Emby.Server.Implementations.SocketSharp; using Emby.Server.Implementations.TV; using Emby.Server.Implementations.Updates; -using Jellyfin.Server.Implementations; -using Jellyfin.Server.Implementations.Activity; using MediaBrowser.Api; using MediaBrowser.Common; using MediaBrowser.Common.Configuration; @@ -547,13 +545,6 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(); - // TODO: properly set up scoping and switch to AddDbContextPool - serviceCollection.AddDbContext( - options => options.UseSqlite($"Filename={Path.Combine(ApplicationPaths.DataPath, "jellyfin.db")}"), - ServiceLifetime.Transient); - - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(_fileSystemManager); serviceCollection.AddSingleton(); @@ -664,8 +655,6 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); serviceCollection.AddSingleton(); diff --git a/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs b/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs index a6eaf2d0a3..305e67e8c3 100644 --- a/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs +++ b/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs @@ -193,12 +193,6 @@ namespace Emby.Server.Implementations.Configuration changed = true; } - if (!config.CameraUploadUpgraded) - { - config.CameraUploadUpgraded = true; - changed = true; - } - if (!config.CollectionsUpgraded) { config.CollectionsUpgraded = true; diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index dccbe2a9a6..896e4310e7 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -9,7 +9,6 @@ - @@ -51,7 +50,7 @@ - netcoreapp3.1 + netstandard2.1 false true diff --git a/Jellyfin.Data/Entities/ActivityLog.cs b/Jellyfin.Data/Entities/ActivityLog.cs index df3026a770..8fbf6eaabf 100644 --- a/Jellyfin.Data/Entities/ActivityLog.cs +++ b/Jellyfin.Data/Entities/ActivityLog.cs @@ -5,34 +5,18 @@ using Microsoft.Extensions.Logging; namespace Jellyfin.Data.Entities { - public partial class ActivityLog + /// + /// An entity referencing an activity log entry. + /// + public partial class ActivityLog : ISavingChanges { - partial void Init(); - - /// - /// Default constructor. Protected due to required properties, but present because EF needs it. - /// - protected ActivityLog() - { - Init(); - } - - /// - /// Replaces default constructor, since it's protected. Caller assumes responsibility for setting all required values before saving. - /// - public static ActivityLog CreateActivityLogUnsafe() - { - return new ActivityLog(); - } - /// - /// Public constructor with required data + /// Initializes a new instance of the class. + /// Public constructor with required data. /// - /// - /// - /// - /// - /// + /// The name. + /// The type. + /// The user id. public ActivityLog(string name, string type, Guid userId) { if (string.IsNullOrEmpty(name)) @@ -54,14 +38,21 @@ namespace Jellyfin.Data.Entities Init(); } + /// + /// Initializes a new instance of the class. + /// Default constructor. Protected due to required properties, but present because EF needs it. + /// + protected ActivityLog() + { + Init(); + } + /// /// Static create function (for use in LINQ queries, etc.) /// - /// - /// - /// - /// - /// + /// The name. + /// The type. + /// The user's id. public static ActivityLog Create(string name, string type, Guid userId) { return new ActivityLog(name, type, userId); @@ -72,7 +63,8 @@ namespace Jellyfin.Data.Entities *************************************************************************/ /// - /// Identity, Indexed, Required + /// Gets the identity of this instance. + /// This is the key in the backing database. /// [Key] [Required] @@ -80,7 +72,8 @@ namespace Jellyfin.Data.Entities public int Id { get; protected set; } /// - /// Required, Max length = 512 + /// Gets or sets the name. + /// Required, Max length = 512. /// [Required] [MaxLength(512)] @@ -88,21 +81,24 @@ namespace Jellyfin.Data.Entities public string Name { get; set; } /// - /// Max length = 512 + /// Gets or sets the overview. + /// Max length = 512. /// [MaxLength(512)] [StringLength(512)] public string Overview { get; set; } /// - /// Max length = 512 + /// Gets or sets the short overview. + /// Max length = 512. /// [MaxLength(512)] [StringLength(512)] public string ShortOverview { get; set; } /// - /// Required, Max length = 256 + /// Gets or sets the type. + /// Required, Max length = 256. /// [Required] [MaxLength(256)] @@ -110,41 +106,48 @@ namespace Jellyfin.Data.Entities public string Type { get; set; } /// - /// Required + /// Gets or sets the user id. + /// Required. /// [Required] public Guid UserId { get; set; } /// - /// Max length = 256 + /// Gets or sets the item id. + /// Max length = 256. /// [MaxLength(256)] [StringLength(256)] public string ItemId { get; set; } /// - /// Required + /// Gets or sets the date created. This should be in UTC. + /// Required. /// [Required] public DateTime DateCreated { get; set; } /// - /// Required + /// Gets or sets the log severity. Default is . + /// Required. /// [Required] public LogLevel LogSeverity { get; set; } /// + /// Gets or sets the row version. /// Required, ConcurrencyToken. /// [ConcurrencyCheck] [Required] public uint RowVersion { get; set; } + partial void Init(); + + /// public void OnSavingChanges() { RowVersion++; } } } - diff --git a/Jellyfin.Data/Jellyfin.Data.csproj b/Jellyfin.Data/Jellyfin.Data.csproj index 8eae366bab..b2a3f7eb34 100644 --- a/Jellyfin.Data/Jellyfin.Data.csproj +++ b/Jellyfin.Data/Jellyfin.Data.csproj @@ -17,14 +17,10 @@ - + - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/Jellyfin.Server.Implementations/Activity/ActivityManager.cs b/Jellyfin.Server.Implementations/Activity/ActivityManager.cs index 531b529dce..0b398b60cd 100644 --- a/Jellyfin.Server.Implementations/Activity/ActivityManager.cs +++ b/Jellyfin.Server.Implementations/Activity/ActivityManager.cs @@ -50,31 +50,31 @@ namespace Jellyfin.Server.Implementations.Activity /// public QueryResult GetPagedResult( - Func, IEnumerable> func, + Func, IQueryable> func, int? startIndex, int? limit) { using var dbContext = _provider.CreateContext(); - var result = func.Invoke(dbContext.ActivityLogs).AsQueryable(); + var query = func(dbContext.ActivityLogs).OrderByDescending(entry => entry.DateCreated).AsQueryable(); if (startIndex.HasValue) { - result = result.Where(entry => entry.Id >= startIndex.Value); + query = query.Skip(startIndex.Value); } if (limit.HasValue) { - result = result.OrderByDescending(entry => entry.DateCreated).Take(limit.Value); + query = query.Take(limit.Value); } // This converts the objects from the new database model to the old for compatibility with the existing API. - var list = result.Select(entry => ConvertToOldModel(entry)).ToList(); + var list = query.AsEnumerable().Select(ConvertToOldModel).ToList(); - return new QueryResult() + return new QueryResult { Items = list, - TotalRecordCount = list.Count + TotalRecordCount = dbContext.ActivityLogs.Count() }; } diff --git a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj index a31f28f64a..149ca50209 100644 --- a/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj +++ b/Jellyfin.Server.Implementations/Jellyfin.Server.Implementations.csproj @@ -25,6 +25,14 @@ + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/Jellyfin.Server.Implementations/JellyfinDb.cs b/Jellyfin.Server.Implementations/JellyfinDb.cs index 6fc8d251b8..23714b24a1 100644 --- a/Jellyfin.Server.Implementations/JellyfinDb.cs +++ b/Jellyfin.Server.Implementations/JellyfinDb.cs @@ -110,7 +110,7 @@ namespace Jellyfin.Server.Implementations foreach (var entity in ChangeTracker.Entries().Where(e => e.State == EntityState.Modified)) { var saveEntity = entity.Entity as ISavingChanges; - saveEntity.OnSavingChanges(); + saveEntity?.OnSavingChanges(); } return base.SaveChanges(); diff --git a/Jellyfin.Server.Implementations/JellyfinDbProvider.cs b/Jellyfin.Server.Implementations/JellyfinDbProvider.cs index 8fdeab0887..eab531d386 100644 --- a/Jellyfin.Server.Implementations/JellyfinDbProvider.cs +++ b/Jellyfin.Server.Implementations/JellyfinDbProvider.cs @@ -27,7 +27,7 @@ namespace Jellyfin.Server.Implementations /// The newly created context. public JellyfinDb CreateContext() { - return _serviceProvider.GetService(); + return _serviceProvider.GetRequiredService(); } } } diff --git a/Jellyfin.Server.Implementations/Migrations/20200502231229_InitialSchema.Designer.cs b/Jellyfin.Server.Implementations/Migrations/20200502231229_InitialSchema.Designer.cs deleted file mode 100644 index e1ee9b34aa..0000000000 --- a/Jellyfin.Server.Implementations/Migrations/20200502231229_InitialSchema.Designer.cs +++ /dev/null @@ -1,73 +0,0 @@ -#pragma warning disable CS1591 -#pragma warning disable SA1601 - -// -using System; -using Jellyfin.Server.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDb))] - [Migration("20200502231229_InitialSchema")] - partial class InitialSchema - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("jellyfin") - .HasAnnotation("ProductVersion", "3.1.3"); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("Overview") - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("ActivityLog"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/Jellyfin.Server.Implementations/Migrations/20200502231229_InitialSchema.cs b/Jellyfin.Server.Implementations/Migrations/20200502231229_InitialSchema.cs deleted file mode 100644 index 42fac865ce..0000000000 --- a/Jellyfin.Server.Implementations/Migrations/20200502231229_InitialSchema.cs +++ /dev/null @@ -1,46 +0,0 @@ -#pragma warning disable CS1591 -#pragma warning disable SA1601 - -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace Jellyfin.Server.Implementations.Migrations -{ - public partial class InitialSchema : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.EnsureSchema( - name: "jellyfin"); - - migrationBuilder.CreateTable( - name: "ActivityLog", - schema: "jellyfin", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("Sqlite:Autoincrement", true), - Name = table.Column(maxLength: 512, nullable: false), - Overview = table.Column(maxLength: 512, nullable: true), - ShortOverview = table.Column(maxLength: 512, nullable: true), - Type = table.Column(maxLength: 256, nullable: false), - UserId = table.Column(nullable: false), - ItemId = table.Column(maxLength: 256, nullable: true), - DateCreated = table.Column(nullable: false), - LogSeverity = table.Column(nullable: false), - RowVersion = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ActivityLog", x => x.Id); - }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "ActivityLog", - schema: "jellyfin"); - } - } -} diff --git a/Jellyfin.Server.Implementations/Migrations/20200514181226_AddActivityLog.Designer.cs b/Jellyfin.Server.Implementations/Migrations/20200514181226_AddActivityLog.Designer.cs new file mode 100644 index 0000000000..98a83b7450 --- /dev/null +++ b/Jellyfin.Server.Implementations/Migrations/20200514181226_AddActivityLog.Designer.cs @@ -0,0 +1,72 @@ +#pragma warning disable CS1591 + +// +using System; +using Jellyfin.Server.Implementations; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +namespace Jellyfin.Server.Implementations.Migrations +{ + [DbContext(typeof(JellyfinDb))] + [Migration("20200514181226_AddActivityLog")] + partial class AddActivityLog + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasDefaultSchema("jellyfin") + .HasAnnotation("ProductVersion", "3.1.3"); + + modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateCreated") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("LogSeverity") + .HasColumnType("INTEGER"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(512); + + b.Property("Overview") + .HasColumnType("TEXT") + .HasMaxLength(512); + + b.Property("RowVersion") + .IsConcurrencyToken() + .HasColumnType("INTEGER"); + + b.Property("ShortOverview") + .HasColumnType("TEXT") + .HasMaxLength(512); + + b.Property("Type") + .IsRequired() + .HasColumnType("TEXT") + .HasMaxLength(256); + + b.Property("UserId") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("ActivityLogs"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Jellyfin.Server.Implementations/Migrations/20200514181226_AddActivityLog.cs b/Jellyfin.Server.Implementations/Migrations/20200514181226_AddActivityLog.cs new file mode 100644 index 0000000000..5e0b454d8b --- /dev/null +++ b/Jellyfin.Server.Implementations/Migrations/20200514181226_AddActivityLog.cs @@ -0,0 +1,46 @@ +#pragma warning disable CS1591 +#pragma warning disable SA1601 + +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +namespace Jellyfin.Server.Implementations.Migrations +{ + public partial class AddActivityLog : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.EnsureSchema( + name: "jellyfin"); + + migrationBuilder.CreateTable( + name: "ActivityLogs", + schema: "jellyfin", + columns: table => new + { + Id = table.Column(nullable: false) + .Annotation("Sqlite:Autoincrement", true), + Name = table.Column(maxLength: 512, nullable: false), + Overview = table.Column(maxLength: 512, nullable: true), + ShortOverview = table.Column(maxLength: 512, nullable: true), + Type = table.Column(maxLength: 256, nullable: false), + UserId = table.Column(nullable: false), + ItemId = table.Column(maxLength: 256, nullable: true), + DateCreated = table.Column(nullable: false), + LogSeverity = table.Column(nullable: false), + RowVersion = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ActivityLogs", x => x.Id); + }); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ActivityLogs", + schema: "jellyfin"); + } + } +} diff --git a/Jellyfin.Server.Implementations/Migrations/DesignTimeJellyfinDbFactory.cs b/Jellyfin.Server.Implementations/Migrations/DesignTimeJellyfinDbFactory.cs index 23a0fdc784..a1b58eb5a9 100644 --- a/Jellyfin.Server.Implementations/Migrations/DesignTimeJellyfinDbFactory.cs +++ b/Jellyfin.Server.Implementations/Migrations/DesignTimeJellyfinDbFactory.cs @@ -1,6 +1,3 @@ -#pragma warning disable CS1591 -#pragma warning disable SA1601 - using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; @@ -15,7 +12,9 @@ namespace Jellyfin.Server.Implementations.Migrations public JellyfinDb CreateDbContext(string[] args) { var optionsBuilder = new DbContextOptionsBuilder(); - optionsBuilder.UseSqlite("Data Source=jellyfin.db"); + optionsBuilder.UseSqlite( + "Data Source=jellyfin.db", + opt => opt.MigrationsAssembly("Jellyfin.Migrations")); return new JellyfinDb(optionsBuilder.Options); } diff --git a/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs b/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs index 27f5fe24b0..1e7ffd2359 100644 --- a/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs +++ b/Jellyfin.Server.Implementations/Migrations/JellyfinDbModelSnapshot.cs @@ -1,9 +1,7 @@ // using System; -using Jellyfin.Server.Implementations; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; namespace Jellyfin.Server.Implementations.Migrations { @@ -60,7 +58,7 @@ namespace Jellyfin.Server.Implementations.Migrations b.HasKey("Id"); - b.ToTable("ActivityLog"); + b.ToTable("ActivityLogs"); }); #pragma warning restore 612, 618 } diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index f678e714c1..331a32c737 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -1,12 +1,17 @@ using System; using System.Collections.Generic; +using System.IO; using System.Reflection; using Emby.Drawing; using Emby.Server.Implementations; using Jellyfin.Drawing.Skia; +using Jellyfin.Server.Implementations; +using Jellyfin.Server.Implementations.Activity; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Drawing; +using MediaBrowser.Model.Activity; using MediaBrowser.Model.IO; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -56,6 +61,15 @@ namespace Jellyfin.Server Logger.LogWarning($"Skia not available. Will fallback to {nameof(NullImageEncoder)}."); } + // TODO: Set up scoping and use AddDbContextPool + serviceCollection.AddDbContext( + options => options.UseSqlite($"Filename={Path.Combine(ApplicationPaths.DataPath, "jellyfin.db")}"), + ServiceLifetime.Transient); + + serviceCollection.AddSingleton(); + + serviceCollection.AddSingleton(); + base.RegisterServices(serviceCollection); } diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 4194070aa9..9eec6ed4eb 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -13,9 +13,6 @@ true true enable - - - True @@ -44,10 +41,6 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - @@ -67,6 +60,7 @@ + diff --git a/MediaBrowser.Api/System/ActivityLogService.cs b/MediaBrowser.Api/System/ActivityLogService.cs index f2c37d7117..a6bacad4fc 100644 --- a/MediaBrowser.Api/System/ActivityLogService.cs +++ b/MediaBrowser.Api/System/ActivityLogService.cs @@ -1,3 +1,7 @@ +using System; +using System.Globalization; +using System.Linq; +using Jellyfin.Data.Entities; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Net; using MediaBrowser.Model.Activity; @@ -47,7 +51,14 @@ namespace MediaBrowser.Api.System public object Get(GetActivityLogs request) { - var result = _activityManager.GetPagedResult(request.StartIndex, request.Limit); + DateTime? minDate = string.IsNullOrWhiteSpace(request.MinDate) ? + (DateTime?)null : + DateTime.Parse(request.MinDate, null, DateTimeStyles.RoundtripKind).ToUniversalTime(); + + var filterFunc = new Func, IQueryable>( + entries => entries.Where(entry => entry.DateCreated >= minDate)); + + var result = _activityManager.GetPagedResult(filterFunc, request.StartIndex, request.Limit); return ToOptimizedResult(result); } diff --git a/MediaBrowser.Model/Activity/IActivityManager.cs b/MediaBrowser.Model/Activity/IActivityManager.cs index 6742dc8fc4..9dab5e77b7 100644 --- a/MediaBrowser.Model/Activity/IActivityManager.cs +++ b/MediaBrowser.Model/Activity/IActivityManager.cs @@ -1,7 +1,6 @@ #pragma warning disable CS1591 using System; -using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Jellyfin.Data.Entities; @@ -21,7 +20,7 @@ namespace MediaBrowser.Model.Activity QueryResult GetPagedResult(int? startIndex, int? limit); QueryResult GetPagedResult( - Func, IEnumerable> func, + Func, IQueryable> func, int? startIndex, int? limit); } diff --git a/MediaBrowser.Model/Configuration/ServerConfiguration.cs b/MediaBrowser.Model/Configuration/ServerConfiguration.cs index 22a42322a6..1f5981f101 100644 --- a/MediaBrowser.Model/Configuration/ServerConfiguration.cs +++ b/MediaBrowser.Model/Configuration/ServerConfiguration.cs @@ -79,8 +79,6 @@ namespace MediaBrowser.Model.Configuration public bool EnableRemoteAccess { get; set; } - public bool CameraUploadUpgraded { get; set; } - public bool CollectionsUpgraded { get; set; } /// diff --git a/MediaBrowser.Model/Devices/DeviceOptions.cs b/MediaBrowser.Model/Devices/DeviceOptions.cs new file mode 100644 index 0000000000..8b77fd7fc3 --- /dev/null +++ b/MediaBrowser.Model/Devices/DeviceOptions.cs @@ -0,0 +1,9 @@ +#pragma warning disable CS1591 + +namespace MediaBrowser.Model.Devices +{ + public class DeviceOptions + { + public string CustomName { get; set; } + } +} diff --git a/MediaBrowser.Model/Devices/DevicesOptions.cs b/MediaBrowser.Model/Devices/DevicesOptions.cs deleted file mode 100644 index 02570650e9..0000000000 --- a/MediaBrowser.Model/Devices/DevicesOptions.cs +++ /dev/null @@ -1,23 +0,0 @@ -#pragma warning disable CS1591 - -using System; - -namespace MediaBrowser.Model.Devices -{ - public class DevicesOptions - { - public string[] EnabledCameraUploadDevices { get; set; } - public string CameraUploadPath { get; set; } - public bool EnableCameraUploadSubfolders { get; set; } - - public DevicesOptions() - { - EnabledCameraUploadDevices = Array.Empty(); - } - } - - public class DeviceOptions - { - public string CustomName { get; set; } - } -} -- cgit v1.2.3