From a6a4cd5667fbb5a793cb9e551ce9c9a9bfb0d44b Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 6 Feb 2019 20:38:42 +0100 Subject: [PATCH 001/104] Removed some unused fields --- BDInfo/BDROM.cs | 4 ++-- BDInfo/TSPlaylistFile.cs | 7 ++----- BDInfo/TSStreamClipFile.cs | 4 +--- .../IsoMounter/LinuxIsoManager.cs | 4 +--- Emby.Photos/PhotoProvider.cs | 5 +---- .../AppBase/BaseConfigurationManager.cs | 2 +- .../AppBase/ConfigurationHelper.cs | 4 +--- .../ApplicationHost.cs | 14 ++++++------- .../Archiving/ZipClient.cs | 6 ++---- .../Collections/CollectionImageProvider.cs | 8 +++++-- .../Collections/CollectionManager.cs | 4 +--- .../Data/CleanDatabaseScheduledTask.cs | 11 +--------- .../Devices/DeviceId.cs | 12 +---------- .../Devices/DeviceManager.cs | 12 ++--------- Emby.Server.Implementations/Dto/DtoService.cs | 12 ----------- .../FFMpeg/FFMpegLoader.cs | 13 ++---------- .../IO/FileRefresher.cs | 10 +-------- .../IO/LibraryMonitor.cs | 21 ++++--------------- .../Library/CoreResolutionIgnoreRule.cs | 14 ++++--------- .../Library/LibraryManager.cs | 4 ++-- .../Library/Resolvers/BaseVideoResolver.cs | 5 +---- .../Library/Resolvers/Movies/MovieResolver.cs | 3 ++- .../Library/Resolvers/PhotoResolver.cs | 8 ++----- .../Library/Resolvers/TV/EpisodeResolver.cs | 4 ++-- .../Library/Resolvers/VideoResolver.cs | 4 ++-- .../Library/UserManager.cs | 5 +---- .../Library/Validators/PeopleValidator.cs | 4 +--- .../LiveTv/EmbyTV/EmbyTV.cs | 6 +++--- .../LiveTv/EmbyTV/EncodedRecorder.cs | 15 ++++++------- .../LiveTv/EmbyTV/ItemDataProvider.cs | 4 +--- .../LiveTv/EmbyTV/SeriesTimerManager.cs | 5 ++--- .../LiveTv/EmbyTV/TimerManager.cs | 5 ++--- .../LiveTv/TunerHosts/BaseTunerHost.cs | 5 +---- .../TunerHosts/HdHomerun/HdHomerunHost.cs | 13 +++++++++--- .../LiveTv/TunerHosts/M3UTunerHost.cs | 9 ++++---- .../LiveTv/TunerHosts/M3uParser.cs | 4 +--- 36 files changed, 85 insertions(+), 185 deletions(-) diff --git a/BDInfo/BDROM.cs b/BDInfo/BDROM.cs index 4360ff1d42..6759ed55ad 100644 --- a/BDInfo/BDROM.cs +++ b/BDInfo/BDROM.cs @@ -165,7 +165,7 @@ namespace BDInfo foreach (var file in files) { PlaylistFiles.Add( - file.Name.ToUpper(), new TSPlaylistFile(this, file, _fileSystem)); + file.Name.ToUpper(), new TSPlaylistFile(this, file)); } } @@ -185,7 +185,7 @@ namespace BDInfo foreach (var file in files) { StreamClipFiles.Add( - file.Name.ToUpper(), new TSStreamClipFile(file, _fileSystem)); + file.Name.ToUpper(), new TSStreamClipFile(file)); } } diff --git a/BDInfo/TSPlaylistFile.cs b/BDInfo/TSPlaylistFile.cs index 6e91f6e408..1cc629b1de 100644 --- a/BDInfo/TSPlaylistFile.cs +++ b/BDInfo/TSPlaylistFile.cs @@ -28,7 +28,6 @@ namespace BDInfo { public class TSPlaylistFile { - private readonly IFileSystem _fileSystem; private FileSystemMetadata FileInfo = null; public string FileType = null; public bool IsInitialized = false; @@ -64,21 +63,19 @@ namespace BDInfo new List(); public TSPlaylistFile(BDROM bdrom, - FileSystemMetadata fileInfo, IFileSystem fileSystem) + FileSystemMetadata fileInfo) { BDROM = bdrom; FileInfo = fileInfo; - _fileSystem = fileSystem; Name = fileInfo.Name.ToUpper(); } public TSPlaylistFile(BDROM bdrom, string name, - List clips, IFileSystem fileSystem) + List clips) { BDROM = bdrom; Name = name; - _fileSystem = fileSystem; IsCustom = true; foreach (var clip in clips) { diff --git a/BDInfo/TSStreamClipFile.cs b/BDInfo/TSStreamClipFile.cs index d840542ba9..e1097b23da 100644 --- a/BDInfo/TSStreamClipFile.cs +++ b/BDInfo/TSStreamClipFile.cs @@ -28,7 +28,6 @@ namespace BDInfo { public class TSStreamClipFile { - private readonly IFileSystem _fileSystem; public FileSystemMetadata FileInfo = null; public string FileType = null; public bool IsValid = false; @@ -37,10 +36,9 @@ namespace BDInfo public Dictionary Streams = new Dictionary(); - public TSStreamClipFile(FileSystemMetadata fileInfo, IFileSystem fileSystem) + public TSStreamClipFile(FileSystemMetadata fileInfo) { FileInfo = fileInfo; - _fileSystem = fileSystem; Name = fileInfo.Name.ToUpper(); } diff --git a/Emby.IsoMounting/IsoMounter/LinuxIsoManager.cs b/Emby.IsoMounting/IsoMounter/LinuxIsoManager.cs index a6fc53953e..943caa3e62 100644 --- a/Emby.IsoMounting/IsoMounter/LinuxIsoManager.cs +++ b/Emby.IsoMounting/IsoMounter/LinuxIsoManager.cs @@ -19,7 +19,6 @@ namespace IsoMounter private readonly IEnvironmentInfo EnvironmentInfo; private readonly bool ExecutablesAvailable; - private readonly IFileSystem FileSystem; private readonly ILogger _logger; private readonly string MountCommand; private readonly string MountPointRoot; @@ -31,11 +30,10 @@ namespace IsoMounter #region Constructor(s) - public LinuxIsoManager(ILogger logger, IFileSystem fileSystem, IEnvironmentInfo environment, IProcessFactory processFactory) + public LinuxIsoManager(ILogger logger, IEnvironmentInfo environment, IProcessFactory processFactory) { EnvironmentInfo = environment; - FileSystem = fileSystem; _logger = logger; ProcessFactory = processFactory; diff --git a/Emby.Photos/PhotoProvider.cs b/Emby.Photos/PhotoProvider.cs index f3457d1055..a4179e6609 100644 --- a/Emby.Photos/PhotoProvider.cs +++ b/Emby.Photos/PhotoProvider.cs @@ -9,7 +9,6 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; using Microsoft.Extensions.Logging; using TagLib; using TagLib.IFD; @@ -21,13 +20,11 @@ namespace Emby.Photos public class PhotoProvider : ICustomMetadataProvider, IForcedProvider, IHasItemChangeMonitor { private readonly ILogger _logger; - private readonly IFileSystem _fileSystem; private IImageProcessor _imageProcessor; - public PhotoProvider(ILogger logger, IFileSystem fileSystem, IImageProcessor imageProcessor) + public PhotoProvider(ILogger logger, IImageProcessor imageProcessor) { _logger = logger; - _fileSystem = fileSystem; _imageProcessor = imageProcessor; } diff --git a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs index 460809e936..d7fa4d4c20 100644 --- a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs +++ b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs @@ -79,7 +79,7 @@ namespace Emby.Server.Implementations.AppBase get { // Lazy load - LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationLoaded, ref _configurationSyncLock, () => (BaseApplicationConfiguration)ConfigurationHelper.GetXmlConfiguration(ConfigurationType, CommonApplicationPaths.SystemConfigurationFilePath, XmlSerializer, FileSystem)); + LazyInitializer.EnsureInitialized(ref _configuration, ref _configurationLoaded, ref _configurationSyncLock, () => (BaseApplicationConfiguration)ConfigurationHelper.GetXmlConfiguration(ConfigurationType, CommonApplicationPaths.SystemConfigurationFilePath, XmlSerializer)); return _configuration; } protected set diff --git a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs index 3faad76e7d..90b97061f3 100644 --- a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs +++ b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs @@ -1,7 +1,6 @@ using System; using System.IO; using System.Linq; -using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; namespace Emby.Server.Implementations.AppBase @@ -18,9 +17,8 @@ namespace Emby.Server.Implementations.AppBase /// The type. /// The path. /// The XML serializer. - /// The file system /// System.Object. - public static object GetXmlConfiguration(Type type, string path, IXmlSerializer xmlSerializer, IFileSystem fileSystem) + public static object GetXmlConfiguration(Type type, string path, IXmlSerializer xmlSerializer) { object configuration; diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index bb475eb2c7..5c7133d058 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -440,7 +440,7 @@ namespace Emby.Server.Implementations { if (_deviceId == null) { - _deviceId = new DeviceId(ApplicationPaths, LoggerFactory, FileSystemManager); + _deviceId = new DeviceId(ApplicationPaths, LoggerFactory); } return _deviceId.Value; @@ -780,7 +780,7 @@ namespace Emby.Server.Implementations InstallationManager = new InstallationManager(LoggerFactory, this, ApplicationPaths, HttpClient, JsonSerializer, ServerConfigurationManager, FileSystemManager, CryptographyProvider, PackageRuntime); RegisterSingleInstance(InstallationManager); - ZipClient = new ZipClient(FileSystemManager); + ZipClient = new ZipClient(); RegisterSingleInstance(ZipClient); HttpResultFactory = new HttpResultFactory(LoggerFactory, FileSystemManager, JsonSerializer, CreateBrotliCompressor()); @@ -820,7 +820,7 @@ namespace Emby.Server.Implementations AuthenticationRepository = GetAuthenticationRepository(); RegisterSingleInstance(AuthenticationRepository); - UserManager = new UserManager(LoggerFactory, ServerConfigurationManager, UserRepository, XmlSerializer, NetworkManager, () => ImageProcessor, () => DtoService, this, JsonSerializer, FileSystemManager, CryptographyProvider); + UserManager = new UserManager(LoggerFactory, ServerConfigurationManager, UserRepository, XmlSerializer, NetworkManager, () => ImageProcessor, () => DtoService, this, JsonSerializer, FileSystemManager); RegisterSingleInstance(UserManager); LibraryManager = new LibraryManager(this, LoggerFactory, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager, () => UserViewManager); @@ -830,7 +830,7 @@ namespace Emby.Server.Implementations var musicManager = new MusicManager(LibraryManager); RegisterSingleInstance(new MusicManager(LibraryManager)); - LibraryMonitor = new LibraryMonitor(LoggerFactory, TaskManager, LibraryManager, ServerConfigurationManager, FileSystemManager, EnvironmentInfo); + LibraryMonitor = new LibraryMonitor(LoggerFactory, LibraryManager, ServerConfigurationManager, FileSystemManager, EnvironmentInfo); RegisterSingleInstance(LibraryMonitor); RegisterSingleInstance(() => new SearchEngine(LoggerFactory, LibraryManager, UserManager)); @@ -859,7 +859,7 @@ namespace Emby.Server.Implementations var encryptionManager = new EncryptionManager(); RegisterSingleInstance(encryptionManager); - DeviceManager = new DeviceManager(AuthenticationRepository, JsonSerializer, LibraryManager, LocalizationManager, UserManager, FileSystemManager, LibraryMonitor, ServerConfigurationManager, LoggerFactory, NetworkManager); + DeviceManager = new DeviceManager(AuthenticationRepository, JsonSerializer, LibraryManager, LocalizationManager, UserManager, FileSystemManager, LibraryMonitor, ServerConfigurationManager); RegisterSingleInstance(DeviceManager); MediaSourceManager = new MediaSourceManager(ItemRepository, ApplicationPaths, LocalizationManager, UserManager, LibraryManager, LoggerFactory, JsonSerializer, FileSystemManager, UserDataManager, () => MediaEncoder); @@ -871,7 +871,7 @@ namespace Emby.Server.Implementations ProviderManager = new ProviderManager(HttpClient, SubtitleManager, ServerConfigurationManager, LibraryMonitor, LoggerFactory, FileSystemManager, ApplicationPaths, () => LibraryManager, JsonSerializer); RegisterSingleInstance(ProviderManager); - DtoService = new DtoService(LoggerFactory, LibraryManager, UserDataManager, ItemRepository, ImageProcessor, ServerConfigurationManager, FileSystemManager, ProviderManager, () => ChannelManager, this, () => DeviceManager, () => MediaSourceManager, () => LiveTvManager); + DtoService = new DtoService(LoggerFactory, LibraryManager, UserDataManager, ItemRepository, ImageProcessor, ProviderManager, this, () => MediaSourceManager, () => LiveTvManager); RegisterSingleInstance(DtoService); ChannelManager = new ChannelManager(UserManager, DtoService, LibraryManager, LoggerFactory, ServerConfigurationManager, FileSystemManager, UserDataManager, JsonSerializer, LocalizationManager, HttpClient, ProviderManager); @@ -1058,7 +1058,7 @@ namespace Emby.Server.Implementations protected virtual FFMpegInfo GetFFMpegInfo() { - return new FFMpegLoader(Logger, ApplicationPaths, HttpClient, ZipClient, FileSystemManager, GetFfmpegInstallInfo()) + return new FFMpegLoader(ApplicationPaths, FileSystemManager, GetFfmpegInstallInfo()) .GetFFMpegInfo(StartupOptions); } diff --git a/Emby.Server.Implementations/Archiving/ZipClient.cs b/Emby.Server.Implementations/Archiving/ZipClient.cs index 1135cf694d..6b0fd2dc6c 100644 --- a/Emby.Server.Implementations/Archiving/ZipClient.cs +++ b/Emby.Server.Implementations/Archiving/ZipClient.cs @@ -14,11 +14,9 @@ namespace Emby.Server.Implementations.Archiving /// public class ZipClient : IZipClient { - private readonly IFileSystem _fileSystem; - - public ZipClient(IFileSystem fileSystem) + public ZipClient() { - _fileSystem = fileSystem; + } /// diff --git a/Emby.Server.Implementations/Collections/CollectionImageProvider.cs b/Emby.Server.Implementations/Collections/CollectionImageProvider.cs index 6aeadda2fb..cdfb5cadf1 100644 --- a/Emby.Server.Implementations/Collections/CollectionImageProvider.cs +++ b/Emby.Server.Implementations/Collections/CollectionImageProvider.cs @@ -10,14 +10,18 @@ using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.IO; namespace Emby.Server.Implementations.Collections { public class CollectionImageProvider : BaseDynamicImageProvider { - public CollectionImageProvider(IFileSystem fileSystem, IProviderManager providerManager, IApplicationPaths applicationPaths, IImageProcessor imageProcessor) : base(fileSystem, providerManager, applicationPaths, imageProcessor) + public CollectionImageProvider( + IFileSystem fileSystem, + IProviderManager providerManager, + IApplicationPaths applicationPaths, + IImageProcessor imageProcessor) + : base(fileSystem, providerManager, applicationPaths, imageProcessor) { } diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs index 812e48a1f8..2b99e0ddfc 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -342,14 +342,12 @@ namespace Emby.Server.Implementations.Collections { private readonly CollectionManager _collectionManager; private readonly IServerConfigurationManager _config; - private readonly IFileSystem _fileSystem; private ILogger _logger; - public CollectionManagerEntryPoint(ICollectionManager collectionManager, IServerConfigurationManager config, IFileSystem fileSystem, ILogger logger) + public CollectionManagerEntryPoint(ICollectionManager collectionManager, IServerConfigurationManager config, ILogger logger) { _collectionManager = (CollectionManager)collectionManager; _config = config; - _fileSystem = fileSystem; _logger = logger; } diff --git a/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs b/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs index dcfe149434..f7743a3c25 100644 --- a/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs +++ b/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs @@ -1,11 +1,8 @@ using System; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Persistence; -using MediaBrowser.Model.IO; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Data @@ -13,18 +10,12 @@ namespace Emby.Server.Implementations.Data public class CleanDatabaseScheduledTask : ILibraryPostScanTask { private readonly ILibraryManager _libraryManager; - private readonly IItemRepository _itemRepo; private readonly ILogger _logger; - private readonly IFileSystem _fileSystem; - private readonly IApplicationPaths _appPaths; - public CleanDatabaseScheduledTask(ILibraryManager libraryManager, IItemRepository itemRepo, ILogger logger, IFileSystem fileSystem, IApplicationPaths appPaths) + public CleanDatabaseScheduledTask(ILibraryManager libraryManager, ILogger logger) { _libraryManager = libraryManager; - _itemRepo = itemRepo; _logger = logger; - _fileSystem = fileSystem; - _appPaths = appPaths; } public Task Run(IProgress progress, CancellationToken cancellationToken) diff --git a/Emby.Server.Implementations/Devices/DeviceId.cs b/Emby.Server.Implementations/Devices/DeviceId.cs index 866bd137ff..495c3436ab 100644 --- a/Emby.Server.Implementations/Devices/DeviceId.cs +++ b/Emby.Server.Implementations/Devices/DeviceId.cs @@ -11,7 +11,6 @@ namespace Emby.Server.Implementations.Devices { private readonly IApplicationPaths _appPaths; private readonly ILogger _logger; - private readonly IFileSystem _fileSystem; private readonly object _syncLock = new object(); @@ -86,19 +85,10 @@ namespace Emby.Server.Implementations.Devices private string _id; - public DeviceId( - IApplicationPaths appPaths, - ILoggerFactory loggerFactory, - IFileSystem fileSystem) + public DeviceId(IApplicationPaths appPaths, ILoggerFactory loggerFactory) { - if (fileSystem == null) - { - throw new ArgumentNullException(nameof(fileSystem)); - } - _appPaths = appPaths; _logger = loggerFactory.CreateLogger("SystemId"); - _fileSystem = fileSystem; } public string Value => _id ?? (_id = GetDeviceId()); diff --git a/Emby.Server.Implementations/Devices/DeviceManager.cs b/Emby.Server.Implementations/Devices/DeviceManager.cs index ec3649bcac..7d6529a675 100644 --- a/Emby.Server.Implementations/Devices/DeviceManager.cs +++ b/Emby.Server.Implementations/Devices/DeviceManager.cs @@ -34,8 +34,6 @@ namespace Emby.Server.Implementations.Devices private readonly IFileSystem _fileSystem; private readonly ILibraryMonitor _libraryMonitor; private readonly IServerConfigurationManager _config; - private readonly ILogger _logger; - private readonly INetworkManager _network; private readonly ILibraryManager _libraryManager; private readonly ILocalizationManager _localizationManager; @@ -55,17 +53,13 @@ namespace Emby.Server.Implementations.Devices IUserManager userManager, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, - IServerConfigurationManager config, - ILoggerFactory loggerFactory, - INetworkManager network) + IServerConfigurationManager config) { _json = json; _userManager = userManager; _fileSystem = fileSystem; _libraryMonitor = libraryMonitor; _config = config; - _logger = loggerFactory.CreateLogger(nameof(DeviceManager)); - _network = network; _libraryManager = libraryManager; _localizationManager = localizationManager; _authRepo = authRepo; @@ -414,14 +408,12 @@ namespace Emby.Server.Implementations.Devices { private readonly DeviceManager _deviceManager; private readonly IServerConfigurationManager _config; - private readonly IFileSystem _fileSystem; private ILogger _logger; - public DeviceManagerEntryPoint(IDeviceManager deviceManager, IServerConfigurationManager config, IFileSystem fileSystem, ILogger logger) + public DeviceManagerEntryPoint(IDeviceManager deviceManager, IServerConfigurationManager config, ILogger logger) { _deviceManager = (DeviceManager)deviceManager; _config = config; - _fileSystem = fileSystem; _logger = logger; } diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index 983eb51e63..2233d3d40c 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -36,13 +36,9 @@ namespace Emby.Server.Implementations.Dto private readonly IItemRepository _itemRepo; private readonly IImageProcessor _imageProcessor; - private readonly IServerConfigurationManager _config; - private readonly IFileSystem _fileSystem; private readonly IProviderManager _providerManager; - private readonly Func _channelManagerFactory; private readonly IApplicationHost _appHost; - private readonly Func _deviceManager; private readonly Func _mediaSourceManager; private readonly Func _livetvManager; @@ -52,12 +48,8 @@ namespace Emby.Server.Implementations.Dto IUserDataManager userDataRepository, IItemRepository itemRepo, IImageProcessor imageProcessor, - IServerConfigurationManager config, - IFileSystem fileSystem, IProviderManager providerManager, - Func channelManagerFactory, IApplicationHost appHost, - Func deviceManager, Func mediaSourceManager, Func livetvManager) { @@ -66,12 +58,8 @@ namespace Emby.Server.Implementations.Dto _userDataRepository = userDataRepository; _itemRepo = itemRepo; _imageProcessor = imageProcessor; - _config = config; - _fileSystem = fileSystem; _providerManager = providerManager; - _channelManagerFactory = channelManagerFactory; _appHost = appHost; - _deviceManager = deviceManager; _mediaSourceManager = mediaSourceManager; _livetvManager = livetvManager; } diff --git a/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs b/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs index 6167d1eaa4..bbf51dd246 100644 --- a/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs +++ b/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs @@ -3,27 +3,19 @@ using System.Collections.Generic; using System.IO; using System.Linq; using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; using MediaBrowser.Model.IO; -using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.FFMpeg { public class FFMpegLoader { - private readonly IHttpClient _httpClient; private readonly IApplicationPaths _appPaths; - private readonly ILogger _logger; - private readonly IZipClient _zipClient; private readonly IFileSystem _fileSystem; private readonly FFMpegInstallInfo _ffmpegInstallInfo; - public FFMpegLoader(ILogger logger, IApplicationPaths appPaths, IHttpClient httpClient, IZipClient zipClient, IFileSystem fileSystem, FFMpegInstallInfo ffmpegInstallInfo) + public FFMpegLoader(IApplicationPaths appPaths, IFileSystem fileSystem, FFMpegInstallInfo ffmpegInstallInfo) { - _logger = logger; _appPaths = appPaths; - _httpClient = httpClient; - _zipClient = zipClient; _fileSystem = fileSystem; _ffmpegInstallInfo = ffmpegInstallInfo; } @@ -115,8 +107,7 @@ namespace Emby.Server.Implementations.FFMpeg var encoderFilename = Path.GetFileName(info.EncoderPath); var probeFilename = Path.GetFileName(info.ProbePath); - foreach (var directory in _fileSystem.GetDirectoryPaths(rootEncoderPath) - .ToList()) + foreach (var directory in _fileSystem.GetDirectoryPaths(rootEncoderPath)) { var allFiles = _fileSystem.GetFilePaths(directory, true).ToList(); diff --git a/Emby.Server.Implementations/IO/FileRefresher.cs b/Emby.Server.Implementations/IO/FileRefresher.cs index 3668f6a7ab..73242d0ade 100644 --- a/Emby.Server.Implementations/IO/FileRefresher.cs +++ b/Emby.Server.Implementations/IO/FileRefresher.cs @@ -17,31 +17,23 @@ namespace Emby.Server.Implementations.IO public class FileRefresher : IDisposable { private ILogger Logger { get; set; } - private ITaskManager TaskManager { get; set; } private ILibraryManager LibraryManager { get; set; } private IServerConfigurationManager ConfigurationManager { get; set; } - private readonly IFileSystem _fileSystem; private readonly List _affectedPaths = new List(); private Timer _timer; private readonly object _timerLock = new object(); public string Path { get; private set; } public event EventHandler Completed; - private readonly IEnvironmentInfo _environmentInfo; - private readonly ILibraryManager _libraryManager; - public FileRefresher(string path, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, ITaskManager taskManager, ILogger logger, IEnvironmentInfo environmentInfo, ILibraryManager libraryManager1) + public FileRefresher(string path, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, ILogger logger) { logger.LogDebug("New file refresher created for {0}", path); Path = path; - _fileSystem = fileSystem; ConfigurationManager = configurationManager; LibraryManager = libraryManager; - TaskManager = taskManager; Logger = logger; - _environmentInfo = environmentInfo; - _libraryManager = libraryManager1; AddPath(path); } diff --git a/Emby.Server.Implementations/IO/LibraryMonitor.cs b/Emby.Server.Implementations/IO/LibraryMonitor.cs index 607a4d333f..d473425115 100644 --- a/Emby.Server.Implementations/IO/LibraryMonitor.cs +++ b/Emby.Server.Implementations/IO/LibraryMonitor.cs @@ -34,7 +34,7 @@ namespace Emby.Server.Implementations.IO /// /// Any file name ending in any of these will be ignored by the watchers /// - private readonly HashSet _alwaysIgnoreFiles = new HashSet(StringComparer.OrdinalIgnoreCase) + private static readonly HashSet _alwaysIgnoreFiles = new HashSet(StringComparer.OrdinalIgnoreCase) { "small.jpg", "albumart.jpg", @@ -44,7 +44,7 @@ namespace Emby.Server.Implementations.IO "TempSBE" }; - private readonly string[] _alwaysIgnoreSubstrings = new string[] + private static readonly string[] _alwaysIgnoreSubstrings = new string[] { // Synology "eaDir", @@ -53,7 +53,7 @@ namespace Emby.Server.Implementations.IO ".actors" }; - private readonly HashSet _alwaysIgnoreExtensions = new HashSet(StringComparer.OrdinalIgnoreCase) + private static readonly HashSet _alwaysIgnoreExtensions = new HashSet(StringComparer.OrdinalIgnoreCase) { // thumbs.db ".db", @@ -123,12 +123,6 @@ namespace Emby.Server.Implementations.IO /// The logger. private ILogger Logger { get; set; } - /// - /// Gets or sets the task manager. - /// - /// The task manager. - private ITaskManager TaskManager { get; set; } - private ILibraryManager LibraryManager { get; set; } private IServerConfigurationManager ConfigurationManager { get; set; } @@ -140,19 +134,12 @@ namespace Emby.Server.Implementations.IO /// public LibraryMonitor( ILoggerFactory loggerFactory, - ITaskManager taskManager, ILibraryManager libraryManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem, IEnvironmentInfo environmentInfo) { - if (taskManager == null) - { - throw new ArgumentNullException(nameof(taskManager)); - } - LibraryManager = libraryManager; - TaskManager = taskManager; Logger = loggerFactory.CreateLogger(GetType().Name); ConfigurationManager = configurationManager; _fileSystem = fileSystem; @@ -541,7 +528,7 @@ namespace Emby.Server.Implementations.IO } } - var newRefresher = new FileRefresher(path, _fileSystem, ConfigurationManager, LibraryManager, TaskManager, Logger, _environmentInfo, LibraryManager); + var newRefresher = new FileRefresher(path, ConfigurationManager, LibraryManager, Logger); newRefresher.Completed += NewRefresher_Completed; _activeRefreshers.Add(newRefresher); } diff --git a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs index 80f746c7a9..c644d13eab 100644 --- a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs +++ b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.IO; using System.Linq; using MediaBrowser.Controller.Entities; @@ -7,7 +6,6 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Resolvers; using MediaBrowser.Model.Extensions; using MediaBrowser.Model.IO; -using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Library { @@ -16,16 +14,14 @@ namespace Emby.Server.Implementations.Library /// public class CoreResolutionIgnoreRule : IResolverIgnoreRule { - private readonly IFileSystem _fileSystem; private readonly ILibraryManager _libraryManager; - private readonly ILogger _logger; private bool _ignoreDotPrefix; /// /// Any folder named in this list will be ignored - can be added to at runtime for extensibility /// - public static readonly Dictionary IgnoreFolders = new List + public static readonly string[] IgnoreFolders = { "metadata", "ps3_update", @@ -50,13 +46,11 @@ namespace Emby.Server.Implementations.Library // macos ".AppleDouble" - }.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); + }; - public CoreResolutionIgnoreRule(IFileSystem fileSystem, ILibraryManager libraryManager, ILogger logger) + public CoreResolutionIgnoreRule(ILibraryManager libraryManager) { - _fileSystem = fileSystem; _libraryManager = libraryManager; - _logger = logger; _ignoreDotPrefix = Environment.OSVersion.Platform != PlatformID.Win32NT; } @@ -117,7 +111,7 @@ namespace Emby.Server.Implementations.Library if (fileInfo.IsDirectory) { // Ignore any folders in our list - if (IgnoreFolders.ContainsKey(filename)) + if (IgnoreFolders.Contains(filename, StringComparer.OrdinalIgnoreCase)) { return true; } diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 064006ebd6..87809cae86 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -986,7 +986,7 @@ namespace Emby.Server.Implementations.Library // Ensure the location is available. Directory.CreateDirectory(ConfigurationManager.ApplicationPaths.PeoplePath); - return new PeopleValidator(this, _logger, ConfigurationManager, _fileSystem).ValidatePeople(cancellationToken, progress); + return new PeopleValidator(this, _logger, _fileSystem).ValidatePeople(cancellationToken, progress); } /// @@ -2543,7 +2543,7 @@ namespace Emby.Server.Implementations.Library var resolvers = new IItemResolver[] { - new GenericVideoResolver(this, _fileSystem) + new GenericVideoResolver(this) }; return ResolvePaths(files, directoryService, null, new LibraryOptions(), null, resolvers) diff --git a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs index d992f8d030..541b13cbe1 100644 --- a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs @@ -6,7 +6,6 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; namespace Emby.Server.Implementations.Library.Resolvers { @@ -18,11 +17,9 @@ namespace Emby.Server.Implementations.Library.Resolvers where T : Video, new() { protected readonly ILibraryManager LibraryManager; - protected readonly IFileSystem FileSystem; - protected BaseVideoResolver(ILibraryManager libraryManager, IFileSystem fileSystem) + protected BaseVideoResolver(ILibraryManager libraryManager) { - FileSystem = fileSystem; LibraryManager = libraryManager; } diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs index 472a3f105c..8485636794 100644 --- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs @@ -548,7 +548,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies private IImageProcessor _imageProcessor; - public MovieResolver(ILibraryManager libraryManager, IFileSystem fileSystem, IImageProcessor imageProcessor) : base(libraryManager, fileSystem) + public MovieResolver(ILibraryManager libraryManager, IImageProcessor imageProcessor) + : base(libraryManager) { _imageProcessor = imageProcessor; } diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs index a3298c5803..db270c398b 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs @@ -7,7 +7,6 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; namespace Emby.Server.Implementations.Library.Resolvers { @@ -15,13 +14,11 @@ namespace Emby.Server.Implementations.Library.Resolvers { private readonly IImageProcessor _imageProcessor; private readonly ILibraryManager _libraryManager; - private readonly IFileSystem _fileSystem; - public PhotoResolver(IImageProcessor imageProcessor, ILibraryManager libraryManager, IFileSystem fileSystem) + public PhotoResolver(IImageProcessor imageProcessor, ILibraryManager libraryManager) { _imageProcessor = imageProcessor; _libraryManager = libraryManager; - _fileSystem = fileSystem; } /// @@ -113,8 +110,7 @@ namespace Emby.Server.Implementations.Library.Resolvers return false; } - return imageProcessor.SupportedInputFormats.Contains((Path.GetExtension(path) ?? string.Empty).TrimStart('.')); + return imageProcessor.SupportedInputFormats.Contains(Path.GetExtension(path).TrimStart('.'), StringComparer.Ordinal); } - } } diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs index fed0904d19..a6d18c9b5a 100644 --- a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs @@ -3,7 +3,6 @@ using System.Linq; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.IO; namespace Emby.Server.Implementations.Library.Resolvers.TV { @@ -74,7 +73,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV return null; } - public EpisodeResolver(ILibraryManager libraryManager, IFileSystem fileSystem) : base(libraryManager, fileSystem) + public EpisodeResolver(ILibraryManager libraryManager) + : base(libraryManager) { } } diff --git a/Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs index 60752a85db..68d5d8b2de 100644 --- a/Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs @@ -1,13 +1,13 @@ using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; -using MediaBrowser.Model.IO; namespace Emby.Server.Implementations.Library.Resolvers { public class GenericVideoResolver : BaseVideoResolver where T : Video, new() { - public GenericVideoResolver(ILibraryManager libraryManager, IFileSystem fileSystem) : base(libraryManager, fileSystem) + public GenericVideoResolver(ILibraryManager libraryManager) + : base(libraryManager) { } } diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs index 3ff84382f2..15cbbdb5ae 100644 --- a/Emby.Server.Implementations/Library/UserManager.cs +++ b/Emby.Server.Implementations/Library/UserManager.cs @@ -74,7 +74,6 @@ namespace Emby.Server.Implementations.Library private readonly Func _dtoServiceFactory; private readonly IServerApplicationHost _appHost; private readonly IFileSystem _fileSystem; - private readonly ICryptoProvider _cryptographyProvider; private IAuthenticationProvider[] _authenticationProviders; private DefaultAuthenticationProvider _defaultAuthenticationProvider; @@ -89,8 +88,7 @@ namespace Emby.Server.Implementations.Library Func dtoServiceFactory, IServerApplicationHost appHost, IJsonSerializer jsonSerializer, - IFileSystem fileSystem, - ICryptoProvider cryptographyProvider) + IFileSystem fileSystem) { _logger = loggerFactory.CreateLogger(nameof(UserManager)); UserRepository = userRepository; @@ -101,7 +99,6 @@ namespace Emby.Server.Implementations.Library _appHost = appHost; _jsonSerializer = jsonSerializer; _fileSystem = fileSystem; - _cryptographyProvider = cryptographyProvider; ConfigurationManager = configurationManager; _users = Array.Empty(); diff --git a/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs b/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs index 0ea543ba01..7899cf01b3 100644 --- a/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs +++ b/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs @@ -24,7 +24,6 @@ namespace Emby.Server.Implementations.Library.Validators /// private readonly ILogger _logger; - private readonly IServerConfigurationManager _config; private readonly IFileSystem _fileSystem; /// @@ -32,11 +31,10 @@ namespace Emby.Server.Implementations.Library.Validators /// /// The library manager. /// The logger. - public PeopleValidator(ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config, IFileSystem fileSystem) + public PeopleValidator(ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem) { _libraryManager = libraryManager; _logger = logger; - _config = config; _fileSystem = fileSystem; } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 84ca130b76..fceb82ba19 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -105,8 +105,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _mediaSourceManager = mediaSourceManager; _streamHelper = streamHelper; - _seriesTimerProvider = new SeriesTimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "seriestimers")); - _timerProvider = new TimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "timers"), _logger); + _seriesTimerProvider = new SeriesTimerManager(jsonSerializer, _logger, Path.Combine(DataPath, "seriestimers")); + _timerProvider = new TimerManager(jsonSerializer, _logger, Path.Combine(DataPath, "timers"), _logger); _timerProvider.TimerFired += _timerProvider_TimerFired; _config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated; @@ -1708,7 +1708,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { if (mediaSource.RequiresLooping || !(mediaSource.Container ?? string.Empty).EndsWith("ts", StringComparison.OrdinalIgnoreCase) || (mediaSource.Protocol != MediaProtocol.File && mediaSource.Protocol != MediaProtocol.Http)) { - return new EncodedRecorder(_logger, _fileSystem, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, _httpClient, _processFactory, _config, _assemblyInfo); + return new EncodedRecorder(_logger, _fileSystem, _mediaEncoder, _config.ApplicationPaths, _jsonSerializer, _processFactory, _config); } return new DirectRecorder(_logger, _httpClient, _fileSystem, _streamHelper); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs index eed2395141..9a9bae2151 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs @@ -7,7 +7,6 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; @@ -17,7 +16,6 @@ using MediaBrowser.Model.Diagnostics; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; -using MediaBrowser.Model.Reflection; using MediaBrowser.Model.Serialization; using Microsoft.Extensions.Logging; @@ -27,7 +25,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { private readonly ILogger _logger; private readonly IFileSystem _fileSystem; - private readonly IHttpClient _httpClient; private readonly IMediaEncoder _mediaEncoder; private readonly IServerApplicationPaths _appPaths; private bool _hasExited; @@ -38,19 +35,23 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private readonly IJsonSerializer _json; private readonly TaskCompletionSource _taskCompletionSource = new TaskCompletionSource(); private readonly IServerConfigurationManager _config; - private readonly IAssemblyInfo _assemblyInfo; - public EncodedRecorder(ILogger logger, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IServerApplicationPaths appPaths, IJsonSerializer json, IHttpClient httpClient, IProcessFactory processFactory, IServerConfigurationManager config, IAssemblyInfo assemblyInfo) + public EncodedRecorder( + ILogger logger, + IFileSystem fileSystem, + IMediaEncoder mediaEncoder, + IServerApplicationPaths appPaths, + IJsonSerializer json, + IProcessFactory processFactory, + IServerConfigurationManager config) { _logger = logger; _fileSystem = fileSystem; _mediaEncoder = mediaEncoder; _appPaths = appPaths; _json = json; - _httpClient = httpClient; _processFactory = processFactory; _config = config; - _assemblyInfo = assemblyInfo; } private static bool CopySubtitles => false; diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs index 6b02eaea82..b825ea3b0b 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs @@ -17,15 +17,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV protected readonly ILogger Logger; private readonly string _dataPath; protected readonly Func EqualityComparer; - private readonly IFileSystem _fileSystem; - public ItemDataProvider(IFileSystem fileSystem, IJsonSerializer jsonSerializer, ILogger logger, string dataPath, Func equalityComparer) + public ItemDataProvider(IJsonSerializer jsonSerializer, ILogger logger, string dataPath, Func equalityComparer) { Logger = logger; _dataPath = dataPath; EqualityComparer = equalityComparer; _jsonSerializer = jsonSerializer; - _fileSystem = fileSystem; } public IReadOnlyList GetAll() diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs index d2ad65a1e9..520b444041 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs @@ -1,6 +1,5 @@ using System; using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; using Microsoft.Extensions.Logging; @@ -8,8 +7,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV { public class SeriesTimerManager : ItemDataProvider { - public SeriesTimerManager(IFileSystem fileSystem, IJsonSerializer jsonSerializer, ILogger logger, string dataPath) - : base(fileSystem, jsonSerializer, logger, dataPath, (r1, r2) => string.Equals(r1.Id, r2.Id, StringComparison.OrdinalIgnoreCase)) + public SeriesTimerManager(IJsonSerializer jsonSerializer, ILogger logger, string dataPath) + : base(jsonSerializer, logger, dataPath, (r1, r2) => string.Equals(r1.Id, r2.Id, StringComparison.OrdinalIgnoreCase)) { } diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs index 1dcb02f43e..3c807a8ead 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs @@ -5,7 +5,6 @@ using System.Linq; using System.Threading; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Model.Events; -using MediaBrowser.Model.IO; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Serialization; using Microsoft.Extensions.Logging; @@ -19,8 +18,8 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV public event EventHandler> TimerFired; - public TimerManager(IFileSystem fileSystem, IJsonSerializer jsonSerializer, ILogger logger, string dataPath, ILogger logger1) - : base(fileSystem, jsonSerializer, logger, dataPath, (r1, r2) => string.Equals(r1.Id, r2.Id, StringComparison.OrdinalIgnoreCase)) + public TimerManager(IJsonSerializer jsonSerializer, ILogger logger, string dataPath, ILogger logger1) + : base(jsonSerializer, logger, dataPath, (r1, r2) => string.Equals(r1.Id, r2.Id, StringComparison.OrdinalIgnoreCase)) { _logger = logger1; } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs index 6d1eff187c..715f600a17 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs @@ -9,7 +9,6 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.Dto; using MediaBrowser.Model.IO; using MediaBrowser.Model.LiveTv; @@ -23,18 +22,16 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts protected readonly IServerConfigurationManager Config; protected readonly ILogger Logger; protected IJsonSerializer JsonSerializer; - protected readonly IMediaEncoder MediaEncoder; protected readonly IFileSystem FileSystem; private readonly ConcurrentDictionary _channelCache = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); - protected BaseTunerHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IFileSystem fileSystem) + protected BaseTunerHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IFileSystem fileSystem) { Config = config; Logger = logger; JsonSerializer = jsonSerializer; - MediaEncoder = mediaEncoder; FileSystem = fileSystem; } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index 77b09a83de..24b100eddc 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -31,15 +31,22 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun private readonly IServerApplicationHost _appHost; private readonly ISocketFactory _socketFactory; private readonly INetworkManager _networkManager; - private readonly IEnvironmentInfo _environment; - public HdHomerunHost(IServerConfigurationManager config, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IHttpClient httpClient, IServerApplicationHost appHost, ISocketFactory socketFactory, INetworkManager networkManager, IEnvironmentInfo environment) : base(config, logger, jsonSerializer, mediaEncoder, fileSystem) + public HdHomerunHost( + IServerConfigurationManager config, + ILogger logger, + IJsonSerializer jsonSerializer, + IFileSystem fileSystem, + IHttpClient httpClient, + IServerApplicationHost appHost, + ISocketFactory socketFactory, + INetworkManager networkManager) + : base(config, logger, jsonSerializer, fileSystem) { _httpClient = httpClient; _appHost = appHost; _socketFactory = socketFactory; _networkManager = networkManager; - _environment = environment; } public string Name => "HD Homerun"; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs index 638796e2ef..fdaaf0bae7 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs @@ -26,15 +26,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { private readonly IHttpClient _httpClient; private readonly IServerApplicationHost _appHost; - private readonly IEnvironmentInfo _environment; private readonly INetworkManager _networkManager; private readonly IMediaSourceManager _mediaSourceManager; - public M3UTunerHost(IServerConfigurationManager config, IMediaSourceManager mediaSourceManager, ILogger logger, IJsonSerializer jsonSerializer, IMediaEncoder mediaEncoder, IFileSystem fileSystem, IHttpClient httpClient, IServerApplicationHost appHost, IEnvironmentInfo environment, INetworkManager networkManager) : base(config, logger, jsonSerializer, mediaEncoder, fileSystem) + public M3UTunerHost(IServerConfigurationManager config, IMediaSourceManager mediaSourceManager, ILogger logger, IJsonSerializer jsonSerializer, IFileSystem fileSystem, IHttpClient httpClient, IServerApplicationHost appHost, INetworkManager networkManager) + : base(config, logger, jsonSerializer, fileSystem) { _httpClient = httpClient; _appHost = appHost; - _environment = environment; _networkManager = networkManager; _mediaSourceManager = mediaSourceManager; } @@ -52,7 +51,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts { var channelIdPrefix = GetFullChannelIdPrefix(info); - var result = await new M3uParser(Logger, FileSystem, _httpClient, _appHost).Parse(info.Url, channelIdPrefix, info.Id, cancellationToken).ConfigureAwait(false); + var result = await new M3uParser(Logger, _httpClient, _appHost).Parse(info.Url, channelIdPrefix, info.Id, cancellationToken).ConfigureAwait(false); return result.Cast().ToList(); } @@ -115,7 +114,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts public async Task Validate(TunerHostInfo info) { - using (var stream = await new M3uParser(Logger, FileSystem, _httpClient, _appHost).GetListingsStream(info.Url, CancellationToken.None).ConfigureAwait(false)) + using (var stream = await new M3uParser(Logger, _httpClient, _appHost).GetListingsStream(info.Url, CancellationToken.None).ConfigureAwait(false)) { } diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index 9a01c42d3b..e66f5b42e2 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -19,14 +19,12 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts public class M3uParser { private readonly ILogger _logger; - private readonly IFileSystem _fileSystem; private readonly IHttpClient _httpClient; private readonly IServerApplicationHost _appHost; - public M3uParser(ILogger logger, IFileSystem fileSystem, IHttpClient httpClient, IServerApplicationHost appHost) + public M3uParser(ILogger logger, IHttpClient httpClient, IServerApplicationHost appHost) { _logger = logger; - _fileSystem = fileSystem; _httpClient = httpClient; _appHost = appHost; } From bcb32ec6adfb2bda767c1a46085dd1a1dbaa3ce0 Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Sun, 10 Feb 2019 01:21:05 -0500 Subject: [PATCH 002/104] Bump version to 10.2.0~rc1 --- SharedVersion.cs | 4 +- .../debian-package-x64/pkg-src/changelog | 100 ++++++++++++++++++ .../fedora-package-x64/pkg-src/jellyfin.spec | 100 +++++++++++++++++- 3 files changed, 200 insertions(+), 4 deletions(-) diff --git a/SharedVersion.cs b/SharedVersion.cs index 70c3096740..294748b773 100644 --- a/SharedVersion.cs +++ b/SharedVersion.cs @@ -1,4 +1,4 @@ using System.Reflection; -[assembly: AssemblyVersion("10.1.0")] -[assembly: AssemblyFileVersion("10.1.0")] +[assembly: AssemblyVersion("10.2.0")] +[assembly: AssemblyFileVersion("10.2.0")] diff --git a/deployment/debian-package-x64/pkg-src/changelog b/deployment/debian-package-x64/pkg-src/changelog index 7f3f12b007..d5872e4a7a 100644 --- a/deployment/debian-package-x64/pkg-src/changelog +++ b/deployment/debian-package-x64/pkg-src/changelog @@ -1,3 +1,103 @@ +jellyfin (10.2.0~rc1) unstable; urgency=medium + + * jellyfin: + * PR452 Use EF Core for Activity database + * PR535 Clean up streambuilder + * PR651 Release 10.1.0 + * PR655 Support trying local branches in submodule + * PR656 Do some logging in MediaInfoService + * PR657 Remove conditions that are always true/false + * PR661 Fix NullRef from progress report + * PR663 Use TagLibSharp Nuget package + * PR664 Revert "Fix segment_time_delta for ffmpeg 4.1" + * PR666 Add cross-platform build for arm64 + * PR668 Return Audio objects from MusicAlbum.Tracks + * PR671 Set EnableRaisingEvents correctly + * PR672 Remove unconditional caching, modified since header and use ETags + * PR677 Fix arm32 Docker + * PR681 Fix Windows build script errors + pin ffmpeg to 4.0 + * PR686 Disable some StyleCop warnings + * PR687 Fix some analyzer warnings + * PR689 Fix RPM package build for fedora + * PR702 Fix debug build on windows + * PR706 Make another docker layer reusable + * PR709 Fix always null expressions + * PR710 Fix a spelling mistake + * PR711 Remove remnants of system events + * PR713 Fix empty statement in DidlBuilder.cs + * PR716 Remove more compile time warnings + * PR721 Change image dimentions from double to int + * PR723 Minor improvements to db code + * PR724 Move Skia back into it's own project + * PR726 Clean up IFileSystem wrappers around stdlib. + * PR727 Change default aspect ratio to 2/3 from 0 + * PR728 Use ffmpeg from jrottenberg/ffmpeg + * PR732 Reworked LocalizationManager to load data async + * PR733 Remove unused function + * PR734 Fix more analyzer warnings + * PR736 Start startup tasks async + * PR737 Add AssemblyInfo for Jellyfin.Drawing.Skia + * PR739 Change multi version logic for movies + * PR740 Remove code for pre-installed plugins & properly check if file exists + * PR756 Make cache dir configurable + * PR757 Fix default aspect ratio + * PR758 Add password field to initial setup + * PR764 Remove dead code, made some functions properly async + * PR769 Fix conditions where the ! was swallowed in #726 + * PR774 reimplement support for plugin repository + * PR782 Remove commented file MediaBrowser.LocalMetadata.Savers.PersonXmlSaver + * PR783 Update builds to use #749 and #756 + * PR788 Fix more warnings + * PR794 Remove MoreLINQ + * PR797 Fix all warnings + * PR798 Cleanup around the api endpoints + * PR800 Add CentOS and update rpm spec for the cachedir option + * PR802 Fix build error + * PR804 Handle new option parser properly + * PR805 Add weblate translation status to README + * PR807 Fix restart script in OS packages + * PR810 Fix loading of rating files + * PR812 Fix up the explicit docs links in the README + * PR819 Some small changes in Device.cs and DidlBuilder.cs + * PR822 Complete rename ImageSize -> ImageDimensions + * PR824 Improved Docker pkgbuild + * PR831 Move some arrays to generics + * PR833 Add await to GetCountries in LocalizationService + * PR834 Add donation badge and reorganize badges + * PR838 Quick style fix + * PR840 Fix more warnings + * PR841 Fix OC badge to all and add forum badge + * PR842 Use VAAPI-enabled ffmpeg + * PR852 Use SQLitePCL.pretty.netstandard on NuGet + * PR853 Fix poor handling of cache directories + * PR8 rebase to latest master + * jellyfin-web: + * PR24 Add Master codeowners + * PR34 Revert "Add Master codeowners" + * PR49 Release 10.1.0 + * PR51 remove more code for sync and camera roll + * PR56 Use English for fallback translations and clean up language files + * PR58 Css slider fixes + * PR62 remove BOM markers + * PR65 Fix profile image not being shown on profile page + * PR73 Dev sync + * PR74 Add download menu option to media items + * PR75 User profile fixes + * PR76 Fix syntax error caused by deminification + * PR79 Remove unused Connect related from the frontend + * PR80 Remove games + * PR92 Added frontend support for a password field on setup + * PR94 Update british strings + * PR95 add display language option back + * PR112 Removed seasonal theme support + * PR116 Consolidate all strings into a single file per language + * PR118 Enable and fix PiP for Safari + * PR119 Make the toggle track visible on all themes + * PR121 Fix syntax error in site.js + * PR127 Change sharedcomponents module to core + + -- Jellyfin Packaging Team Sun, 10 Feb 2019 01:18:23 -0500 + jellyfin (10.1.0-1) unstable; urgency=medium * jellyfin: diff --git a/deployment/fedora-package-x64/pkg-src/jellyfin.spec b/deployment/fedora-package-x64/pkg-src/jellyfin.spec index 851c400445..343d23e91e 100644 --- a/deployment/fedora-package-x64/pkg-src/jellyfin.spec +++ b/deployment/fedora-package-x64/pkg-src/jellyfin.spec @@ -7,8 +7,8 @@ %endif Name: jellyfin -Version: 10.1.0 -Release: 1%{?dist} +Version: 10.2.0 +Release: rc1%{?dist} Summary: The Free Software Media Browser License: GPLv2 URL: https://jellyfin.media @@ -140,6 +140,102 @@ fi %systemd_postun_with_restart jellyfin.service %changelog +* Sun Feb 10 2019 Jellyfin Packaging Team +- jellyfin: +- PR452 Use EF Core for Activity database +- PR535 Clean up streambuilder +- PR651 Release 10.1.0 +- PR655 Support trying local branches in submodule +- PR656 Do some logging in MediaInfoService +- PR657 Remove conditions that are always true/false +- PR661 Fix NullRef from progress report +- PR663 Use TagLibSharp Nuget package +- PR664 Revert "Fix segment_time_delta for ffmpeg 4.1" +- PR666 Add cross-platform build for arm64 +- PR668 Return Audio objects from MusicAlbum.Tracks +- PR671 Set EnableRaisingEvents correctly +- PR672 Remove unconditional caching, modified since header and use ETags +- PR677 Fix arm32 Docker +- PR681 Fix Windows build script errors + pin ffmpeg to 4.0 +- PR686 Disable some StyleCop warnings +- PR687 Fix some analyzer warnings +- PR689 Fix RPM package build for fedora +- PR702 Fix debug build on windows +- PR706 Make another docker layer reusable +- PR709 Fix always null expressions +- PR710 Fix a spelling mistake +- PR711 Remove remnants of system events +- PR713 Fix empty statement in DidlBuilder.cs +- PR716 Remove more compile time warnings +- PR721 Change image dimentions from double to int +- PR723 Minor improvements to db code +- PR724 Move Skia back into it's own project +- PR726 Clean up IFileSystem wrappers around stdlib. +- PR727 Change default aspect ratio to 2/3 from 0 +- PR728 Use ffmpeg from jrottenberg/ffmpeg +- PR732 Reworked LocalizationManager to load data async +- PR733 Remove unused function +- PR734 Fix more analyzer warnings +- PR736 Start startup tasks async +- PR737 Add AssemblyInfo for Jellyfin.Drawing.Skia +- PR739 Change multi version logic for movies +- PR740 Remove code for pre-installed plugins & properly check if file exists +- PR756 Make cache dir configurable +- PR757 Fix default aspect ratio +- PR758 Add password field to initial setup +- PR764 Remove dead code, made some functions properly async +- PR769 Fix conditions where the ! was swallowed in #726 +- PR774 reimplement support for plugin repository +- PR782 Remove commented file MediaBrowser.LocalMetadata.Savers.PersonXmlSaver +- PR783 Update builds to use #749 and #756 +- PR788 Fix more warnings +- PR794 Remove MoreLINQ +- PR797 Fix all warnings +- PR798 Cleanup around the api endpoints +- PR800 Add CentOS and update rpm spec for the cachedir option +- PR802 Fix build error +- PR804 Handle new option parser properly +- PR805 Add weblate translation status to README +- PR807 Fix restart script in OS packages +- PR810 Fix loading of rating files +- PR812 Fix up the explicit docs links in the README +- PR819 Some small changes in Device.cs and DidlBuilder.cs +- PR822 Complete rename ImageSize -> ImageDimensions +- PR824 Improved Docker pkgbuild +- PR831 Move some arrays to generics +- PR833 Add await to GetCountries in LocalizationService +- PR834 Add donation badge and reorganize badges +- PR838 Quick style fix +- PR840 Fix more warnings +- PR841 Fix OC badge to all and add forum badge +- PR842 Use VAAPI-enabled ffmpeg +- PR852 Use SQLitePCL.pretty.netstandard on NuGet +- PR853 Fix poor handling of cache directories +- PR8 rebase to latest master +- jellyfin-web: +- PR24 Add Master codeowners +- PR34 Revert "Add Master codeowners" +- PR49 Release 10.1.0 +- PR51 remove more code for sync and camera roll +- PR56 Use English for fallback translations and clean up language files +- PR58 Css slider fixes +- PR62 remove BOM markers +- PR65 Fix profile image not being shown on profile page +- PR73 Dev sync +- PR74 Add download menu option to media items +- PR75 User profile fixes +- PR76 Fix syntax error caused by deminification +- PR79 Remove unused Connect related from the frontend +- PR80 Remove games +- PR92 Added frontend support for a password field on setup +- PR94 Update british strings +- PR95 add display language option back +- PR112 Removed seasonal theme support +- PR116 Consolidate all strings into a single file per language +- PR118 Enable and fix PiP for Safari +- PR119 Make the toggle track visible on all themes +- PR121 Fix syntax error in site.js +- PR127 Change sharedcomponents module to core * Sun Jan 20 2019 Jellyfin Packaging Team - jellyfin: - PR335 Build scripts and build system consolidation. From 30ec203effac33896e25f67d9e30ea4ac649cc5c Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Sun, 10 Feb 2019 20:57:31 +0100 Subject: [PATCH 003/104] Added first test for dotnet-compat ABI testing to drone. --- .drone.yml | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++ .editorconfig | 4 +++ 2 files changed, 100 insertions(+) diff --git a/.drone.yml b/.drone.yml index 98db4884bd..5493e427c6 100644 --- a/.drone.yml +++ b/.drone.yml @@ -6,7 +6,103 @@ steps: image: docker:git commands: - git submodule update --init --recursive + - name: build image: microsoft/dotnet:2-sdk commands: - dotnet publish --configuration release --output /release Jellyfin.Server + +- name: clone-dotnet-compat + image: docker:git + commands: + - git clone --depth 1 https://github.com/EraYaN/dotnet-compatibility + when: + event: + - pull_request + +- name: build-dotnet-compat + image: microsoft/dotnet:2-sdk + commands: + - dotnet publish --configuration release --output /tools dotnet-compatibility/CompatibilityCheckerCoreCLI + when: + event: + - pull_request + +- name: download-last-nuget-release-common + image: plugins/download + settings: + source: https://www.nuget.org/api/v2/package/Jellyfin.Common + destination: Jellyfin.Common.nupkg + when: + event: + - pull_request + +- name: download-last-nuget-release-model + image: plugins/download + settings: + source: https://www.nuget.org/api/v2/package/Jellyfin.Model + destination: Jellyfin.Model.nupkg + when: + event: + - pull_request + +- name: download-last-nuget-release-controller + image: plugins/download + settings: + source: https://www.nuget.org/api/v2/package/Jellyfin.Controller + destination: Jellyfin.Controller.nupkg + when: + event: + - pull_request + +- name: download-last-nuget-release-naming + image: plugins/download + settings: + source: https://www.nuget.org/api/v2/package/Jellyfin.Naming + destination: Jellyfin.Naming.nupkg + when: + event: + - pull_request + +- name: extract-downloaded-nuget-packages + image: garthk/unzip + commands: + - unzip -j Jellyfin.Common.nupkg "*.dll" -d /current-release + - unzip -j Jellyfin.Model.nupkg "*.dll" -d /current-release + - unzip -j Jellyfin.Controller.nupkg "*.dll" -d /current-release + - unzip -j Jellyfin.Naming.nupkg "*.dll" -d /current-release + when: + event: + - pull_request + +- name: run-dotnet-compat-common + image: microsoft/dotnet:2-runtime + commands: + - dotnet /tools/CompatibilityCheckerCoreCLI /current-release/Jellyfin.Common.dll /release/Jellyfin.Common.dll + when: + event: + - pull_request + +- name: run-dotnet-compat-model + image: microsoft/dotnet:2-runtime + commands: + - dotnet /tools/CompatibilityCheckerCoreCLI /current-release/Jellyfin.Model.dll /release/Jellyfin.Model.dll + when: + event: + - pull_request + +- name: run-dotnet-compat-controller + image: microsoft/dotnet:2-runtime + commands: + - dotnet /tools/CompatibilityCheckerCoreCLI /current-release/Jellyfin.Controller.dll /release/Jellyfin.Controller.dll + when: + event: + - pull_request + +- name: run-dotnet-compat-naming + image: microsoft/dotnet:2-runtime + commands: + - dotnet /tools/CompatibilityCheckerCoreCLI /current-release/Jellyfin.Naming.dll /release/Jellyfin.Naming.dll + when: + event: + - pull_request diff --git a/.editorconfig b/.editorconfig index b2891188d8..5034f364e2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -15,6 +15,10 @@ insert_final_newline = true end_of_line = lf max_line_length = null +# YAML indentation +[*.{yml,yaml}] +indent_size = 2 + # XML indentation [*.{csproj,xml}] indent_size = 2 From 236e21efcb8ad0bbad2b3d0b6fc8735f3659d291 Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Sun, 10 Feb 2019 21:04:39 +0100 Subject: [PATCH 004/104] Fixed extension of compat checker and added err_ignore flag. --- .drone.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.drone.yml b/.drone.yml index 5493e427c6..82a9ce7da1 100644 --- a/.drone.yml +++ b/.drone.yml @@ -77,32 +77,36 @@ steps: - name: run-dotnet-compat-common image: microsoft/dotnet:2-runtime + err_ignore: true commands: - - dotnet /tools/CompatibilityCheckerCoreCLI /current-release/Jellyfin.Common.dll /release/Jellyfin.Common.dll + - dotnet /tools/CompatibilityCheckerCoreCLI.dll /current-release/Jellyfin.Common.dll /release/Jellyfin.Common.dll when: event: - pull_request - name: run-dotnet-compat-model image: microsoft/dotnet:2-runtime + err_ignore: true commands: - - dotnet /tools/CompatibilityCheckerCoreCLI /current-release/Jellyfin.Model.dll /release/Jellyfin.Model.dll + - dotnet /tools/CompatibilityCheckerCoreCLI.dll /current-release/Jellyfin.Model.dll /release/Jellyfin.Model.dll when: event: - pull_request - name: run-dotnet-compat-controller image: microsoft/dotnet:2-runtime + err_ignore: true commands: - - dotnet /tools/CompatibilityCheckerCoreCLI /current-release/Jellyfin.Controller.dll /release/Jellyfin.Controller.dll + - dotnet /tools/CompatibilityCheckerCoreCLI.dll /current-release/Jellyfin.Controller.dll /release/Jellyfin.Controller.dll when: event: - pull_request - name: run-dotnet-compat-naming image: microsoft/dotnet:2-runtime + err_ignore: true commands: - - dotnet /tools/CompatibilityCheckerCoreCLI /current-release/Jellyfin.Naming.dll /release/Jellyfin.Naming.dll + - dotnet /tools/CompatibilityCheckerCoreCLI.dll /current-release/Jellyfin.Naming.dll /release/Jellyfin.Naming.dll when: event: - pull_request From 29d678347187ab85a597c88ea72b2ce752094b37 Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Sun, 10 Feb 2019 21:10:03 +0100 Subject: [PATCH 005/104] Switched to debian for the compat runners. --- .drone.yml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.drone.yml b/.drone.yml index 82a9ce7da1..95fe94e704 100644 --- a/.drone.yml +++ b/.drone.yml @@ -23,7 +23,7 @@ steps: - name: build-dotnet-compat image: microsoft/dotnet:2-sdk commands: - - dotnet publish --configuration release --output /tools dotnet-compatibility/CompatibilityCheckerCoreCLI + - dotnet publish --runtime debian.9-x64 --configuration release --output /tools dotnet-compatibility/CompatibilityCheckerCoreCLI when: event: - pull_request @@ -76,37 +76,37 @@ steps: - pull_request - name: run-dotnet-compat-common - image: microsoft/dotnet:2-runtime + image: debian:stretch err_ignore: true commands: - - dotnet /tools/CompatibilityCheckerCoreCLI.dll /current-release/Jellyfin.Common.dll /release/Jellyfin.Common.dll + - /tools/CompatibilityCheckerCoreCLI /current-release/Jellyfin.Common.dll /release/Jellyfin.Common.dll when: event: - pull_request - name: run-dotnet-compat-model - image: microsoft/dotnet:2-runtime + image: debian:stretch err_ignore: true commands: - - dotnet /tools/CompatibilityCheckerCoreCLI.dll /current-release/Jellyfin.Model.dll /release/Jellyfin.Model.dll + - /tools/CompatibilityCheckerCoreCLI /current-release/Jellyfin.Model.dll /release/Jellyfin.Model.dll when: event: - pull_request - name: run-dotnet-compat-controller - image: microsoft/dotnet:2-runtime + image: debian:stretch err_ignore: true commands: - - dotnet /tools/CompatibilityCheckerCoreCLI.dll /current-release/Jellyfin.Controller.dll /release/Jellyfin.Controller.dll + - /tools/CompatibilityCheckerCoreCLI /current-release/Jellyfin.Controller.dll /release/Jellyfin.Controller.dll when: event: - pull_request - name: run-dotnet-compat-naming - image: microsoft/dotnet:2-runtime + image: debian:stretch err_ignore: true commands: - - dotnet /tools/CompatibilityCheckerCoreCLI.dll /current-release/Jellyfin.Naming.dll /release/Jellyfin.Naming.dll + - /tools/CompatibilityCheckerCoreCLI /current-release/Jellyfin.Naming.dll /release/Jellyfin.Naming.dll when: event: - pull_request From 9849c183ac649db640c3ca5a646b88665918c3fa Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Sun, 10 Feb 2019 12:27:45 -0500 Subject: [PATCH 006/104] Fix syntax error of additional brace --- deployment/win-x64/package.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/deployment/win-x64/package.sh b/deployment/win-x64/package.sh index befddb2e76..d21e3b5325 100755 --- a/deployment/win-x64/package.sh +++ b/deployment/win-x64/package.sh @@ -1,4 +1,5 @@ #!/usr/bin/env bash +set -x package_win64() ( local NSSM_VERSION="nssm-2.24-101-g897c7ad" local NSSM_URL="https://nssm.cc/ci/${NSSM_VERSION}.zip" @@ -15,7 +16,7 @@ package_win64() ( wget ${NSSM_URL} -O ${TEMP_DIR}/nssm.zip wget ${FFMPEG_URL} -O ${TEMP_DIR}/ffmpeg.zip unzip ${TEMP_DIR}/nssm.zip -d $TEMP_DIR - cp ${TEMP_DIR}/${NSSM_VERSION}}/win64/nssm.exe ${OUTPUT_DIR}/nssm.exe + cp ${TEMP_DIR}/${NSSM_VERSION}/win64/nssm.exe ${OUTPUT_DIR}/nssm.exe unzip ${TEMP_DIR}/ffmpeg.zip -d $TEMP_DIR cp ${TEMP_DIR}/${FFMPEG_VERSION}/bin/ffmpeg.exe ${OUTPUT_DIR}/ffmpeg.exe cp ${TEMP_DIR}/${FFMPEG_VERSION}/bin/ffprobe.exe ${OUTPUT_DIR}/ffprobe.exe From 86089ec03a4af121281154a6159cc70787571dbe Mon Sep 17 00:00:00 2001 From: Felix Ruhnow Date: Sun, 10 Feb 2019 22:23:47 +0100 Subject: [PATCH 007/104] Adding support for "tvg-chno"-Tag in M3U Channel Lists --- .../LiveTv/TunerHosts/M3uParser.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index 9a01c42d3b..e10c445019 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -204,6 +204,14 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts } } + if (!IsValidChannelNumber(numberString)) + { + if (attributes.TryGetValue("tvg-chno", out string value)) + { + numberString = value; + } + } + if (!string.IsNullOrWhiteSpace(numberString)) { numberString = numberString.Trim(); From 2f4a00d322e355babfc73aa5d9e546491a02fad8 Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Sun, 10 Feb 2019 17:29:55 -0500 Subject: [PATCH 008/104] Add support for ZIP plugin archives Most code from @cvium. Also removes the lazy and ill-conceived GUID- based checksumming, which just died with ZIP archives. --- .../ApplicationHost.cs | 10 ++--- .../Updates/InstallationManager.cs | 44 +++++++++---------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index bb475eb2c7..3538244064 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -564,7 +564,7 @@ namespace Emby.Server.Implementations { try { - var assembly = Assembly.Load(File.ReadAllBytes(file)); + var assembly = Assembly.LoadFrom(file); return new Tuple(assembly, file); } @@ -777,12 +777,12 @@ namespace Emby.Server.Implementations SocketFactory = new SocketFactory(); RegisterSingleInstance(SocketFactory); - InstallationManager = new InstallationManager(LoggerFactory, this, ApplicationPaths, HttpClient, JsonSerializer, ServerConfigurationManager, FileSystemManager, CryptographyProvider, PackageRuntime); - RegisterSingleInstance(InstallationManager); - ZipClient = new ZipClient(FileSystemManager); RegisterSingleInstance(ZipClient); + InstallationManager = new InstallationManager(LoggerFactory, this, ApplicationPaths, HttpClient, JsonSerializer, ServerConfigurationManager, FileSystemManager, CryptographyProvider, ZipClient, PackageRuntime); + RegisterSingleInstance(InstallationManager); + HttpResultFactory = new HttpResultFactory(LoggerFactory, FileSystemManager, JsonSerializer, CreateBrotliCompressor()); RegisterSingleInstance(HttpResultFactory); @@ -1603,7 +1603,7 @@ namespace Emby.Server.Implementations { try { - return FilterAssembliesToLoad(Directory.EnumerateFiles(path, "*.dll", SearchOption.TopDirectoryOnly)) + return FilterAssembliesToLoad(Directory.EnumerateFiles(path, "*.dll", SearchOption.AllDirectories)) .Select(LoadAssembly) .Where(a => a != null) .ToList(); diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index dc7f57f27d..127b9c62ab 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -116,6 +116,7 @@ namespace Emby.Server.Implementations.Updates private readonly IApplicationHost _applicationHost; private readonly ICryptoProvider _cryptographyProvider; + private readonly IZipClient _zipClient; // netframework or netcore private readonly string _packageRuntime; @@ -129,6 +130,7 @@ namespace Emby.Server.Implementations.Updates IServerConfigurationManager config, IFileSystem fileSystem, ICryptoProvider cryptographyProvider, + IZipClient zipClient, string packageRuntime) { if (loggerFactory == null) @@ -146,6 +148,7 @@ namespace Emby.Server.Implementations.Updates _config = config; _fileSystem = fileSystem; _cryptographyProvider = cryptographyProvider; + _zipClient = zipClient; _packageRuntime = packageRuntime; _logger = loggerFactory.CreateLogger(nameof(InstallationManager)); } @@ -527,13 +530,19 @@ namespace Emby.Server.Implementations.Updates private async Task PerformPackageInstallation(IProgress progress, string target, PackageVersionInfo package, CancellationToken cancellationToken) { // Target based on if it is an archive or single assembly - // zip archives are assumed to contain directory structures relative to our ProgramDataPath var extension = Path.GetExtension(package.targetFilename); - var isArchive = string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase) || string.Equals(extension, ".rar", StringComparison.OrdinalIgnoreCase) || string.Equals(extension, ".7z", StringComparison.OrdinalIgnoreCase); + var isArchive = string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase); if (target == null) { - target = Path.Combine(isArchive ? _appPaths.TempUpdatePath : _appPaths.PluginsPath, package.targetFilename); + if (isArchive) + { + target = Path.Combine(_appPaths.PluginsPath, Path.GetFileNameWithoutExtension(package.targetFilename)); + } + else + { + target = Path.Combine(_appPaths.PluginsPath, package.targetFilename); + } } // Download to temporary file so that, if interrupted, it won't destroy the existing installation @@ -547,31 +556,22 @@ namespace Emby.Server.Implementations.Updates cancellationToken.ThrowIfCancellationRequested(); - // Validate with a checksum - var packageChecksum = string.IsNullOrWhiteSpace(package.checksum) ? Guid.Empty : new Guid(package.checksum); - if (!packageChecksum.Equals(Guid.Empty)) // support for legacy uploads for now - { - using (var stream = File.OpenRead(tempFile)) - { - var check = Guid.Parse(BitConverter.ToString(_cryptographyProvider.ComputeMD5(stream)).Replace("-", string.Empty)); - if (check != packageChecksum) - { - throw new Exception(string.Format("Download validation failed for {0}. Probably corrupted during transfer.", package.name)); - } - } - } - - cancellationToken.ThrowIfCancellationRequested(); + // TODO: Validate with a checksum, *properly* // Success - move it to the real target try { - Directory.CreateDirectory(Path.GetDirectoryName(target)); - File.Copy(tempFile, target, true); - //If it is an archive - write out a version file so we know what it is if (isArchive) { - File.WriteAllText(target + ".ver", package.versionStr); + using (var stream = File.OpenRead(tempFile)) + { + _zipClient.ExtractAllFromZip(stream, target, true); + } + } + else + { + Directory.CreateDirectory(Path.GetDirectoryName(target)); + File.Copy(tempFile, target, true); } } catch (IOException ex) From edf5ee0cc43beaff4437ace4ae6b0202e414ec03 Mon Sep 17 00:00:00 2001 From: Felix Ruhnow Date: Mon, 11 Feb 2019 10:11:07 +0100 Subject: [PATCH 009/104] combining some of the if's and adressing #820 --- .../LiveTv/TunerHosts/M3uParser.cs | 88 +++++++++---------- 1 file changed, 42 insertions(+), 46 deletions(-) diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs index e10c445019..d2a835b850 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs @@ -157,64 +157,56 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts var nameInExtInf = nameParts.Length > 1 ? nameParts.Last().Trim() : null; string numberString = null; + string attributeValue; + double doubleValue; - // Check for channel number with the format from SatIp - // #EXTINF:0,84. VOX Schweiz - // #EXTINF:0,84.0 - VOX Schweiz - if (!string.IsNullOrWhiteSpace(nameInExtInf)) + if (attributes.TryGetValue("tvg-chno", out attributeValue)) { - var numberIndex = nameInExtInf.IndexOf(' '); - if (numberIndex > 0) + if (double.TryParse(attributeValue, NumberStyles.Any, CultureInfo.InvariantCulture, out doubleValue)) { - var numberPart = nameInExtInf.Substring(0, numberIndex).Trim(new[] { ' ', '.' }); + numberString = attributeValue; + } + } - if (double.TryParse(numberPart, NumberStyles.Any, CultureInfo.InvariantCulture, out var number)) + if (!IsValidChannelNumber(numberString)) + { + if (attributes.TryGetValue("tvg-id", out attributeValue)) + { + if (double.TryParse(attributeValue, NumberStyles.Any, CultureInfo.InvariantCulture, out doubleValue)) { - numberString = numberPart; + numberString = attributeValue; + } + else if (attributes.TryGetValue("channel-id", out attributeValue)) + { + if (double.TryParse(attributeValue, NumberStyles.Any, CultureInfo.InvariantCulture, out doubleValue)) + { + numberString = attributeValue; + } } } - } - if (!string.IsNullOrWhiteSpace(numberString)) - { - numberString = numberString.Trim(); - } - - if (!IsValidChannelNumber(numberString)) - { - if (attributes.TryGetValue("tvg-id", out string value)) + if (String.IsNullOrWhiteSpace(numberString)) { - if (double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var doubleValue)) + // Using this as a fallback now as this leads to Problems with channels like "5 USA" + // where 5 isnt ment to be the channel number + // Check for channel number with the format from SatIp + // #EXTINF:0,84. VOX Schweiz + // #EXTINF:0,84.0 - VOX Schweiz + if (!string.IsNullOrWhiteSpace(nameInExtInf)) { - numberString = value; + var numberIndex = nameInExtInf.IndexOf(' '); + if (numberIndex > 0) + { + var numberPart = nameInExtInf.Substring(0, numberIndex).Trim(new[] { ' ', '.' }); + + if (double.TryParse(numberPart, NumberStyles.Any, CultureInfo.InvariantCulture, out var number)) + { + numberString = numberPart; + } + } } } - } - if (!string.IsNullOrWhiteSpace(numberString)) - { - numberString = numberString.Trim(); - } - - if (!IsValidChannelNumber(numberString)) - { - if (attributes.TryGetValue("channel-id", out string value)) - { - numberString = value; - } - } - - if (!IsValidChannelNumber(numberString)) - { - if (attributes.TryGetValue("tvg-chno", out string value)) - { - numberString = value; - } - } - - if (!string.IsNullOrWhiteSpace(numberString)) - { - numberString = numberString.Trim(); } if (!IsValidChannelNumber(numberString)) @@ -222,7 +214,11 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts numberString = null; } - if (string.IsNullOrWhiteSpace(numberString)) + if (!string.IsNullOrWhiteSpace(numberString)) + { + numberString = numberString.Trim(); + } + else { if (string.IsNullOrWhiteSpace(mediaUrl)) { From d8cb34dbbc3d4c86794836cb48116bebd885f0e5 Mon Sep 17 00:00:00 2001 From: William Lees Date: Tue, 12 Feb 2019 00:24:00 +1100 Subject: [PATCH 010/104] add httpClient to appropriate constructors --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 4 +++- MediaBrowser.Api/Playback/Progressive/AudioService.cs | 5 ++++- .../Playback/Progressive/BaseProgressiveStreamingService.cs | 4 +++- MediaBrowser.Api/Playback/Progressive/VideoService.cs | 5 ++++- MediaBrowser.Api/Playback/UniversalAudioService.cs | 6 +++++- 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 0736862989..693a69e1b1 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -71,7 +71,7 @@ namespace MediaBrowser.Api.Playback protected IMediaSourceManager MediaSourceManager { get; private set; } protected IJsonSerializer JsonSerializer { get; private set; } - public static IHttpClient HttpClient; + public static IHttpClient HttpClient { get; private set; } protected IAuthorizationContext AuthorizationContext { get; private set; } protected EncodingHelper EncodingHelper { get; set; } @@ -80,6 +80,7 @@ namespace MediaBrowser.Api.Playback /// Initializes a new instance of the class. /// protected BaseStreamingService( + IHttpClient httpClient, IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, @@ -93,6 +94,7 @@ namespace MediaBrowser.Api.Playback IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext) { + HttpClient = httpClient; ServerConfigurationManager = serverConfig; UserManager = userManager; LibraryManager = libraryManager; diff --git a/MediaBrowser.Api/Playback/Progressive/AudioService.cs b/MediaBrowser.Api/Playback/Progressive/AudioService.cs index 208a5560d2..48b4e2f24e 100644 --- a/MediaBrowser.Api/Playback/Progressive/AudioService.cs +++ b/MediaBrowser.Api/Playback/Progressive/AudioService.cs @@ -1,4 +1,5 @@ using System.Threading.Tasks; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; @@ -33,6 +34,7 @@ namespace MediaBrowser.Api.Playback.Progressive public class AudioService : BaseProgressiveStreamingService { public AudioService( + IHttpClient httpClient, IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, @@ -46,7 +48,8 @@ namespace MediaBrowser.Api.Playback.Progressive IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, IEnvironmentInfo environmentInfo) - : base(serverConfig, + : base(httpClient, + serverConfig, userManager, libraryManager, isoManager, diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index c197de1739..7f4f8af0ba 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -28,6 +28,7 @@ namespace MediaBrowser.Api.Playback.Progressive protected readonly IEnvironmentInfo EnvironmentInfo; public BaseProgressiveStreamingService( + IHttpClient httpClient, IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, @@ -41,7 +42,8 @@ namespace MediaBrowser.Api.Playback.Progressive IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, IEnvironmentInfo environmentInfo) - : base(serverConfig, + : base(httpClient, + serverConfig, userManager, libraryManager, isoManager, diff --git a/MediaBrowser.Api/Playback/Progressive/VideoService.cs b/MediaBrowser.Api/Playback/Progressive/VideoService.cs index a0ea5c62d9..7aeb0e9e85 100644 --- a/MediaBrowser.Api/Playback/Progressive/VideoService.cs +++ b/MediaBrowser.Api/Playback/Progressive/VideoService.cs @@ -1,4 +1,5 @@ using System.Threading.Tasks; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; @@ -69,6 +70,7 @@ namespace MediaBrowser.Api.Playback.Progressive public class VideoService : BaseProgressiveStreamingService { public VideoService( + IHttpClient httpClient, IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, @@ -82,7 +84,8 @@ namespace MediaBrowser.Api.Playback.Progressive IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, IEnvironmentInfo environmentInfo) - : base(serverConfig, + : base(httpClient, + serverConfig, userManager, libraryManager, isoManager, diff --git a/MediaBrowser.Api/Playback/UniversalAudioService.cs b/MediaBrowser.Api/Playback/UniversalAudioService.cs index e07770a4c4..f97e88e986 100644 --- a/MediaBrowser.Api/Playback/UniversalAudioService.cs +++ b/MediaBrowser.Api/Playback/UniversalAudioService.cs @@ -77,6 +77,7 @@ namespace MediaBrowser.Api.Playback public class UniversalAudioService : BaseApiService { public UniversalAudioService( + IHttpClient httpClient, IServerConfigurationManager serverConfigurationManager, IUserManager userManager, ILibraryManager libraryManager, @@ -95,6 +96,7 @@ namespace MediaBrowser.Api.Playback IEnvironmentInfo environmentInfo, ILoggerFactory loggerFactory) { + HttpClient = httpClient; ServerConfigurationManager = serverConfigurationManager; UserManager = userManager; LibraryManager = libraryManager; @@ -115,6 +117,7 @@ namespace MediaBrowser.Api.Playback _logger = loggerFactory.CreateLogger(nameof(UniversalAudioService)); } + protected IHttpClient HttpClient { get; private set; } protected IServerConfigurationManager ServerConfigurationManager { get; private set; } protected IUserManager UserManager { get; private set; } protected ILibraryManager LibraryManager { get; private set; } @@ -323,7 +326,8 @@ namespace MediaBrowser.Api.Playback } else { - var service = new AudioService(ServerConfigurationManager, + var service = new AudioService(HttpClient, + ServerConfigurationManager, UserManager, LibraryManager, IsoManager, From 250f03d2d9b06cc2cc7b3346dcddb4959ea8d365 Mon Sep 17 00:00:00 2001 From: William Lees Date: Tue, 12 Feb 2019 00:42:33 +1100 Subject: [PATCH 011/104] add httpClient to more constructors --- MediaBrowser.Api/Playback/Hls/BaseHlsService.cs | 5 ++++- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 4 +++- MediaBrowser.Api/Playback/Hls/VideoHlsService.cs | 5 ++++- MediaBrowser.Api/Playback/UniversalAudioService.cs | 3 ++- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 1acc42ea52..77ebc6e8f9 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -4,6 +4,7 @@ using System.IO; using System.Text; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; @@ -314,6 +315,7 @@ namespace MediaBrowser.Api.Playback.Hls } public BaseHlsService( + IHttpClient httpClient, IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, @@ -326,7 +328,8 @@ namespace MediaBrowser.Api.Playback.Hls IMediaSourceManager mediaSourceManager, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext) - : base(serverConfig, + : base(httpClient, + serverConfig, userManager, libraryManager, isoManager, diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 45f003cae8..98648d4971 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -96,6 +96,7 @@ namespace MediaBrowser.Api.Playback.Hls { public DynamicHlsService( + IHttpClient httpClient, IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, @@ -109,7 +110,8 @@ namespace MediaBrowser.Api.Playback.Hls IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, INetworkManager networkManager) - : base(serverConfig, + : base(httpClient, + serverConfig, userManager, libraryManager, isoManager, diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index eb1bbfb74b..60fb72d446 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; @@ -132,6 +133,7 @@ namespace MediaBrowser.Api.Playback.Hls } public VideoHlsService( + IHttpClient httpClient, IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, @@ -144,7 +146,8 @@ namespace MediaBrowser.Api.Playback.Hls IMediaSourceManager mediaSourceManager, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext) - : base(serverConfig, + : base(httpClient, + serverConfig, userManager, libraryManager, isoManager, diff --git a/MediaBrowser.Api/Playback/UniversalAudioService.cs b/MediaBrowser.Api/Playback/UniversalAudioService.cs index f97e88e986..8d0aef7218 100644 --- a/MediaBrowser.Api/Playback/UniversalAudioService.cs +++ b/MediaBrowser.Api/Playback/UniversalAudioService.cs @@ -280,7 +280,8 @@ namespace MediaBrowser.Api.Playback if (!isStatic && string.Equals(mediaSource.TranscodingSubProtocol, "hls", StringComparison.OrdinalIgnoreCase)) { - var service = new DynamicHlsService(ServerConfigurationManager, + var service = new DynamicHlsService(HttpClient, + ServerConfigurationManager, UserManager, LibraryManager, IsoManager, From da169dddb5b19e09833f3874d78a0305ed89cef1 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Mon, 11 Feb 2019 18:52:09 +0100 Subject: [PATCH 012/104] Remove DLL support and require all packages/plugins to be zip archives --- .../Updates/InstallationManager.cs | 27 ++++++------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 127b9c62ab..f03a594cde 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -529,20 +529,17 @@ namespace Emby.Server.Implementations.Updates private async Task PerformPackageInstallation(IProgress progress, string target, PackageVersionInfo package, CancellationToken cancellationToken) { - // Target based on if it is an archive or single assembly var extension = Path.GetExtension(package.targetFilename); var isArchive = string.Equals(extension, ".zip", StringComparison.OrdinalIgnoreCase); + if (!isArchive) + { + _logger.LogError("Only zip packages are supported. {Filename} is not a zip archive.", package.targetFilename); + return; + } if (target == null) { - if (isArchive) - { - target = Path.Combine(_appPaths.PluginsPath, Path.GetFileNameWithoutExtension(package.targetFilename)); - } - else - { - target = Path.Combine(_appPaths.PluginsPath, package.targetFilename); - } + target = Path.Combine(_appPaths.PluginsPath, Path.GetFileNameWithoutExtension(package.targetFilename)); } // Download to temporary file so that, if interrupted, it won't destroy the existing installation @@ -561,17 +558,9 @@ namespace Emby.Server.Implementations.Updates // Success - move it to the real target try { - if (isArchive) + using (var stream = File.OpenRead(tempFile)) { - using (var stream = File.OpenRead(tempFile)) - { - _zipClient.ExtractAllFromZip(stream, target, true); - } - } - else - { - Directory.CreateDirectory(Path.GetDirectoryName(target)); - File.Copy(tempFile, target, true); + _zipClient.ExtractAllFromZip(stream, target, true); } } catch (IOException ex) From 32992b614346c90543425135603662e5fcffce46 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Mon, 11 Feb 2019 18:53:35 +0100 Subject: [PATCH 013/104] Add extra linebreak --- Emby.Server.Implementations/Updates/InstallationManager.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index f03a594cde..adf609e20d 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -537,6 +537,7 @@ namespace Emby.Server.Implementations.Updates _logger.LogError("Only zip packages are supported. {Filename} is not a zip archive.", package.targetFilename); return; } + if (target == null) { target = Path.Combine(_appPaths.PluginsPath, Path.GetFileNameWithoutExtension(package.targetFilename)); From 406fb045c26ca7fcf653024e2cbb8a487c3774bf Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Mon, 11 Feb 2019 18:54:10 +0100 Subject: [PATCH 014/104] Change logging to match the action --- Emby.Server.Implementations/Updates/InstallationManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index adf609e20d..301802b8a6 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -566,7 +566,7 @@ namespace Emby.Server.Implementations.Updates } catch (IOException ex) { - _logger.LogError(ex, "Error attempting to move file from {TempFile} to {TargetFile}", tempFile, target); + _logger.LogError(ex, "Error attempting to extract {TempFile} to {TargetFile}", tempFile, target); throw; } From db4a72df10b52dbeaf8d3a6d7256b5898be6b569 Mon Sep 17 00:00:00 2001 From: William Lees Date: Tue, 12 Feb 2019 09:23:51 +1100 Subject: [PATCH 015/104] Reduce scope of changes --- MediaBrowser.Api/Playback/BaseStreamingService.cs | 4 ---- MediaBrowser.Api/Playback/Hls/BaseHlsService.cs | 5 +---- MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs | 4 +--- MediaBrowser.Api/Playback/Hls/VideoHlsService.cs | 5 +---- .../Playback/Progressive/BaseProgressiveStreamingService.cs | 5 +++-- MediaBrowser.Api/Playback/UniversalAudioService.cs | 3 +-- 6 files changed, 7 insertions(+), 19 deletions(-) diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs index 693a69e1b1..a6be071b84 100644 --- a/MediaBrowser.Api/Playback/BaseStreamingService.cs +++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs @@ -8,7 +8,6 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; @@ -71,7 +70,6 @@ namespace MediaBrowser.Api.Playback protected IMediaSourceManager MediaSourceManager { get; private set; } protected IJsonSerializer JsonSerializer { get; private set; } - public static IHttpClient HttpClient { get; private set; } protected IAuthorizationContext AuthorizationContext { get; private set; } protected EncodingHelper EncodingHelper { get; set; } @@ -80,7 +78,6 @@ namespace MediaBrowser.Api.Playback /// Initializes a new instance of the class. /// protected BaseStreamingService( - IHttpClient httpClient, IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, @@ -94,7 +91,6 @@ namespace MediaBrowser.Api.Playback IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext) { - HttpClient = httpClient; ServerConfigurationManager = serverConfig; UserManager = userManager; LibraryManager = libraryManager; diff --git a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs index 77ebc6e8f9..1acc42ea52 100644 --- a/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/BaseHlsService.cs @@ -4,7 +4,6 @@ using System.IO; using System.Text; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; @@ -315,7 +314,6 @@ namespace MediaBrowser.Api.Playback.Hls } public BaseHlsService( - IHttpClient httpClient, IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, @@ -328,8 +326,7 @@ namespace MediaBrowser.Api.Playback.Hls IMediaSourceManager mediaSourceManager, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext) - : base(httpClient, - serverConfig, + : base(serverConfig, userManager, libraryManager, isoManager, diff --git a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs index 98648d4971..45f003cae8 100644 --- a/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/DynamicHlsService.cs @@ -96,7 +96,6 @@ namespace MediaBrowser.Api.Playback.Hls { public DynamicHlsService( - IHttpClient httpClient, IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, @@ -110,8 +109,7 @@ namespace MediaBrowser.Api.Playback.Hls IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, INetworkManager networkManager) - : base(httpClient, - serverConfig, + : base(serverConfig, userManager, libraryManager, isoManager, diff --git a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs index 60fb72d446..eb1bbfb74b 100644 --- a/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs +++ b/MediaBrowser.Api/Playback/Hls/VideoHlsService.cs @@ -1,6 +1,5 @@ using System; using System.Threading.Tasks; -using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; @@ -133,7 +132,6 @@ namespace MediaBrowser.Api.Playback.Hls } public VideoHlsService( - IHttpClient httpClient, IServerConfigurationManager serverConfig, IUserManager userManager, ILibraryManager libraryManager, @@ -146,8 +144,7 @@ namespace MediaBrowser.Api.Playback.Hls IMediaSourceManager mediaSourceManager, IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext) - : base(httpClient, - serverConfig, + : base(serverConfig, userManager, libraryManager, isoManager, diff --git a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs index 7f4f8af0ba..6a98c5e8a6 100644 --- a/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs +++ b/MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs @@ -26,6 +26,7 @@ namespace MediaBrowser.Api.Playback.Progressive public abstract class BaseProgressiveStreamingService : BaseStreamingService { protected readonly IEnvironmentInfo EnvironmentInfo; + protected IHttpClient HttpClient { get; private set; } public BaseProgressiveStreamingService( IHttpClient httpClient, @@ -42,8 +43,7 @@ namespace MediaBrowser.Api.Playback.Progressive IJsonSerializer jsonSerializer, IAuthorizationContext authorizationContext, IEnvironmentInfo environmentInfo) - : base(httpClient, - serverConfig, + : base(serverConfig, userManager, libraryManager, isoManager, @@ -57,6 +57,7 @@ namespace MediaBrowser.Api.Playback.Progressive authorizationContext) { EnvironmentInfo = environmentInfo; + HttpClient = httpClient; } /// diff --git a/MediaBrowser.Api/Playback/UniversalAudioService.cs b/MediaBrowser.Api/Playback/UniversalAudioService.cs index 8d0aef7218..f97e88e986 100644 --- a/MediaBrowser.Api/Playback/UniversalAudioService.cs +++ b/MediaBrowser.Api/Playback/UniversalAudioService.cs @@ -280,8 +280,7 @@ namespace MediaBrowser.Api.Playback if (!isStatic && string.Equals(mediaSource.TranscodingSubProtocol, "hls", StringComparison.OrdinalIgnoreCase)) { - var service = new DynamicHlsService(HttpClient, - ServerConfigurationManager, + var service = new DynamicHlsService(ServerConfigurationManager, UserManager, LibraryManager, IsoManager, From d18823ced179b08b2cf50d84c85d3ee0b635a3ce Mon Sep 17 00:00:00 2001 From: William Lees Date: Tue, 12 Feb 2019 23:28:02 +1100 Subject: [PATCH 016/104] Fix potential NullReferenceException --- MediaBrowser.Model/Dlna/StreamBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs index 6c6e09ab1c..586e322e48 100644 --- a/MediaBrowser.Model/Dlna/StreamBuilder.cs +++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs @@ -297,7 +297,7 @@ namespace MediaBrowser.Model.Dlna int? inputAudioChannels = audioStream?.Channels; int? inputAudioBitrate = audioStream?.BitDepth; int? inputAudioSampleRate = audioStream?.SampleRate; - int? inputAudioBitDepth = audioStream.BitDepth; + int? inputAudioBitDepth = audioStream?.BitDepth; if (directPlayMethods.Count() > 0) { From fe43e279c83da1269ff774ab9af7c493f788fcf3 Mon Sep 17 00:00:00 2001 From: William Lees Date: Tue, 12 Feb 2019 23:50:53 +1100 Subject: [PATCH 017/104] Add to contributors --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 5e3455fba5..28690f36fa 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -18,6 +18,7 @@ - [dkanada](https://github.com/dkanada) - [LogicalPhallacy](https://github.com/LogicalPhallacy/) - [RazeLighter777](https://github.com/RazeLighter777) + - [WillWill56](https://github.com/WillWill56) # Emby Contributors From 8055b70ab13fb0b06bc8bc81adc6f8bc1ce38b6c Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Tue, 12 Feb 2019 16:21:46 +0100 Subject: [PATCH 018/104] Fixed full pipeline, runs correctly now with `drone exec` --- .dockerignore | 1 + .drone.yml | 71 ++++++++++++++------------------------------------- .gitignore | 2 ++ 3 files changed, 22 insertions(+), 52 deletions(-) diff --git a/.dockerignore b/.dockerignore index 45e5435258..ffd6de2d66 100644 --- a/.dockerignore +++ b/.dockerignore @@ -8,3 +8,4 @@ README.md deployment/*/dist deployment/*/pkg-dist deployment/collect-dist/ +ci/ diff --git a/.drone.yml b/.drone.yml index 95fe94e704..f1212d3f96 100644 --- a/.drone.yml +++ b/.drone.yml @@ -10,103 +10,70 @@ steps: - name: build image: microsoft/dotnet:2-sdk commands: - - dotnet publish --configuration release --output /release Jellyfin.Server + - dotnet publish "Jellyfin.Server" --configuration Release --output "../ci/ci-release" - name: clone-dotnet-compat image: docker:git commands: - - git clone --depth 1 https://github.com/EraYaN/dotnet-compatibility - when: - event: - - pull_request + - git clone --depth 1 https://github.com/EraYaN/dotnet-compatibility ci/dotnet-compatibility - name: build-dotnet-compat image: microsoft/dotnet:2-sdk commands: - - dotnet publish --runtime debian.9-x64 --configuration release --output /tools dotnet-compatibility/CompatibilityCheckerCoreCLI - when: - event: - - pull_request + - dotnet publish "ci/dotnet-compatibility/CompatibilityCheckerCoreCLI" --configuration Release --output "../../ci-tools" - name: download-last-nuget-release-common image: plugins/download settings: source: https://www.nuget.org/api/v2/package/Jellyfin.Common - destination: Jellyfin.Common.nupkg - when: - event: - - pull_request + destination: ci/Jellyfin.Common.nupkg - name: download-last-nuget-release-model image: plugins/download settings: source: https://www.nuget.org/api/v2/package/Jellyfin.Model - destination: Jellyfin.Model.nupkg - when: - event: - - pull_request + destination: ci/Jellyfin.Model.nupkg - name: download-last-nuget-release-controller image: plugins/download settings: source: https://www.nuget.org/api/v2/package/Jellyfin.Controller - destination: Jellyfin.Controller.nupkg - when: - event: - - pull_request + destination: ci/Jellyfin.Controller.nupkg - name: download-last-nuget-release-naming image: plugins/download settings: source: https://www.nuget.org/api/v2/package/Jellyfin.Naming - destination: Jellyfin.Naming.nupkg - when: - event: - - pull_request + destination: ci/Jellyfin.Naming.nupkg - name: extract-downloaded-nuget-packages image: garthk/unzip commands: - - unzip -j Jellyfin.Common.nupkg "*.dll" -d /current-release - - unzip -j Jellyfin.Model.nupkg "*.dll" -d /current-release - - unzip -j Jellyfin.Controller.nupkg "*.dll" -d /current-release - - unzip -j Jellyfin.Naming.nupkg "*.dll" -d /current-release - when: - event: - - pull_request + - unzip -j ci/Jellyfin.Common.nupkg "*.dll" -d ci/nuget-packages + - unzip -j ci/Jellyfin.Model.nupkg "*.dll" -d ci/nuget-packages + - unzip -j ci/Jellyfin.Controller.nupkg "*.dll" -d ci/nuget-packages + - unzip -j ci/Jellyfin.Naming.nupkg "*.dll" -d ci/nuget-packages - name: run-dotnet-compat-common - image: debian:stretch + image: microsoft/dotnet:2-runtime err_ignore: true commands: - - /tools/CompatibilityCheckerCoreCLI /current-release/Jellyfin.Common.dll /release/Jellyfin.Common.dll - when: - event: - - pull_request + - dotnet ci/ci-tools/CompatibilityCheckerCoreCLI.dll ci/nuget-packages/Jellyfin.Common.dll ci/ci-release/Jellyfin.Common.dll - name: run-dotnet-compat-model - image: debian:stretch + image: microsoft/dotnet:2-runtime err_ignore: true commands: - - /tools/CompatibilityCheckerCoreCLI /current-release/Jellyfin.Model.dll /release/Jellyfin.Model.dll - when: - event: - - pull_request + - dotnet ci/ci-tools/CompatibilityCheckerCoreCLI.dll ci/nuget-packages/Jellyfin.Model.dll ci/ci-release/Jellyfin.Model.dll - name: run-dotnet-compat-controller - image: debian:stretch + image: microsoft/dotnet:2-runtime err_ignore: true commands: - - /tools/CompatibilityCheckerCoreCLI /current-release/Jellyfin.Controller.dll /release/Jellyfin.Controller.dll - when: - event: - - pull_request + - dotnet ci/ci-tools/CompatibilityCheckerCoreCLI.dll ci/nuget-packages/Jellyfin.Controller.dll ci/ci-release/Jellyfin.Controller.dll - name: run-dotnet-compat-naming - image: debian:stretch + image: microsoft/dotnet:2-runtime err_ignore: true commands: - - /tools/CompatibilityCheckerCoreCLI /current-release/Jellyfin.Naming.dll /release/Jellyfin.Naming.dll - when: - event: - - pull_request + - dotnet ci/ci-tools/CompatibilityCheckerCoreCLI.dll ci/nuget-packages/Jellyfin.Naming.dll ci/ci-release/Jellyfin.Naming.dll diff --git a/.gitignore b/.gitignore index aef6662727..65e47747ee 100644 --- a/.gitignore +++ b/.gitignore @@ -264,3 +264,5 @@ deployment/**/pkg-dist-tmp/ deployment/collect-dist/ jellyfin_version.ini + +ci/ From 33e069e4615215c95e948c04745240cdd6ad78ec Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Thu, 7 Feb 2019 15:13:13 +0000 Subject: [PATCH 019/104] Translated using Weblate (Dutch) Currently translated at 96.8% (91 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/nl/ --- Emby.Server.Implementations/Localization/Core/nl.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/nl.json b/Emby.Server.Implementations/Localization/Core/nl.json index 589753c446..ad6b160473 100644 --- a/Emby.Server.Implementations/Localization/Core/nl.json +++ b/Emby.Server.Implementations/Localization/Core/nl.json @@ -9,20 +9,20 @@ "Channels": "Kanalen", "ChapterNameValue": "Hoofdstuk {0}", "Collections": "Collecties", - "DeviceOfflineWithName": "{0} is losgekoppeld", + "DeviceOfflineWithName": "{0} heeft de verbinding verbroken", "DeviceOnlineWithName": "{0} is verbonden", "FailedLoginAttemptWithUserName": "Mislukte aanmeld poging van {0}", "Favorites": "Favorieten", "Folders": "Mappen", "Genres": "Genres", - "HeaderAlbumArtists": "Album artiesten", - "HeaderCameraUploads": "Camera uploads", + "HeaderAlbumArtists": "Albumartiesten", + "HeaderCameraUploads": "Camera-uploads", "HeaderContinueWatching": "Kijken hervatten", "HeaderFavoriteAlbums": "Favoriete albums", "HeaderFavoriteArtists": "Favoriete artiesten", "HeaderFavoriteEpisodes": "Favoriete afleveringen", "HeaderFavoriteShows": "Favoriete shows", - "HeaderFavoriteSongs": "Favoriete titels", + "HeaderFavoriteSongs": "Favoriete nummers", "HeaderLiveTV": "Live TV", "HeaderNextUp": "Volgende", "HeaderRecordingGroups": "Opnamegroepen", @@ -34,7 +34,7 @@ "LabelRunningTimeValue": "Looptijd: {0}", "Latest": "Nieuwste", "MessageApplicationUpdated": "Jellyfin Server is bijgewerkt", - "MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}", + "MessageApplicationUpdatedTo": "Jellyfin Server is bijgewerkt naar {0}", "MessageNamedServerConfigurationUpdatedWithValue": "Sectie {0} van de server configuratie is bijgewerkt", "MessageServerConfigurationUpdated": "Server configuratie is bijgewerkt", "MixedContent": "Gemengde inhoud", From e150174ecedab0db3dd03144bb696372ad4c7b86 Mon Sep 17 00:00:00 2001 From: bakkegaard Date: Wed, 6 Feb 2019 14:38:27 +0000 Subject: [PATCH 020/104] Translated using Weblate (Danish) Currently translated at 98.9% (93 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/da/ --- Emby.Server.Implementations/Localization/Core/da.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/da.json b/Emby.Server.Implementations/Localization/Core/da.json index 7004d44dba..51f3a46a6e 100644 --- a/Emby.Server.Implementations/Localization/Core/da.json +++ b/Emby.Server.Implementations/Localization/Core/da.json @@ -5,7 +5,7 @@ "Artists": "Kunstner", "AuthenticationSucceededWithUserName": "{0} bekræftet med succes", "Books": "Bøger", - "CameraImageUploadedFrom": "A new camera image has been uploaded from {0}", + "CameraImageUploadedFrom": "Et nye billede fra kamera er blevet uploadet fra {0}", "Channels": "Kanaler", "ChapterNameValue": "Kapitel {0}", "Collections": "Samlinger", @@ -16,7 +16,7 @@ "Folders": "Mapper", "Genres": "Genre", "HeaderAlbumArtists": "Albumkunstnere", - "HeaderCameraUploads": "Camera Uploads", + "HeaderCameraUploads": "Kamera Uploads", "HeaderContinueWatching": "Fortsæt Afspilning", "HeaderFavoriteAlbums": "Favoritalbum", "HeaderFavoriteArtists": "Favoritkunstnere", From 3b96c78515aa117f11a93a92b90d7f1d1f040c9e Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Thu, 7 Feb 2019 15:17:01 +0000 Subject: [PATCH 021/104] Translated using Weblate (English (United States)) Currently translated at 100.0% (94 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/en_US/ --- Emby.Server.Implementations/Localization/Core/en-US.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/en-US.json b/Emby.Server.Implementations/Localization/Core/en-US.json index f19cd532b9..aa855ed21f 100644 --- a/Emby.Server.Implementations/Localization/Core/en-US.json +++ b/Emby.Server.Implementations/Localization/Core/en-US.json @@ -30,7 +30,7 @@ "Inherit": "Inherit", "ItemAddedWithName": "{0} was added to the library", "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip address: {0}", + "LabelIpAddressValue": "IP address: {0}", "LabelRunningTimeValue": "Running time: {0}", "Latest": "Latest", "MessageApplicationUpdated": "Jellyfin Server has been updated", From 2f377e0a0fbc92366f62c8f8b4fecd829ac76f10 Mon Sep 17 00:00:00 2001 From: Hadrien Miche Date: Wed, 6 Feb 2019 09:19:39 +0000 Subject: [PATCH 022/104] Translated using Weblate (French) Currently translated at 98.9% (93 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/fr/ --- Emby.Server.Implementations/Localization/Core/fr.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/fr.json b/Emby.Server.Implementations/Localization/Core/fr.json index aa9a1add3e..52afb4e492 100644 --- a/Emby.Server.Implementations/Localization/Core/fr.json +++ b/Emby.Server.Implementations/Localization/Core/fr.json @@ -36,7 +36,7 @@ "MessageApplicationUpdated": "Le serveur Jellyfin a été mis à jour", "MessageApplicationUpdatedTo": "Jellyfin Serveur a été mis à jour en version {0}", "MessageNamedServerConfigurationUpdatedWithValue": "La configuration de la section {0} du serveur a été mise à jour", - "MessageServerConfigurationUpdated": "La configuration du serveur a été mise à jour.", + "MessageServerConfigurationUpdated": "La configuration du serveur a été mise à jour", "MixedContent": "Contenu mixte", "Movies": "Films", "Music": "Musique", From 269b94254bdefb1fa8d819e2ed7bb83d2418e8ac Mon Sep 17 00:00:00 2001 From: ZsiGiT Date: Mon, 4 Feb 2019 18:17:55 +0000 Subject: [PATCH 023/104] Translated using Weblate (Hungarian) Currently translated at 98.9% (93 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/hu/ --- .../Localization/Core/hu.json | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/hu.json b/Emby.Server.Implementations/Localization/Core/hu.json index d2d16b18fe..911fe36db2 100644 --- a/Emby.Server.Implementations/Localization/Core/hu.json +++ b/Emby.Server.Implementations/Localization/Core/hu.json @@ -5,48 +5,48 @@ "Artists": "Előadók", "AuthenticationSucceededWithUserName": "{0} sikeresen azonosítva", "Books": "Könyvek", - "CameraImageUploadedFrom": "A new camera image has been uploaded from {0}", + "CameraImageUploadedFrom": "Új kamerakép került feltöltésre {0}", "Channels": "Csatornák", "ChapterNameValue": "Jelenet {0}", "Collections": "Gyűjtemények", "DeviceOfflineWithName": "{0} kijelentkezett", "DeviceOnlineWithName": "{0} belépett", - "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", + "FailedLoginAttemptWithUserName": "Sikertelen bejelentkezési kísérlet {0}", "Favorites": "Kedvencek", "Folders": "Könyvtárak", "Genres": "Műfajok", "HeaderAlbumArtists": "Album Előadók", - "HeaderCameraUploads": "Camera Uploads", + "HeaderCameraUploads": "Kamera feltöltések", "HeaderContinueWatching": "Vetítés(ek) folytatása", "HeaderFavoriteAlbums": "Kedvenc Albumok", "HeaderFavoriteArtists": "Kedvenc Művészek", "HeaderFavoriteEpisodes": "Kedvenc Epizódok", "HeaderFavoriteShows": "Kedvenc Műsorok", "HeaderFavoriteSongs": "Kedvenc Dalok", - "HeaderLiveTV": "Live TV", + "HeaderLiveTV": "Élő TV", "HeaderNextUp": "Következik", - "HeaderRecordingGroups": "Recording Groups", + "HeaderRecordingGroups": "Felvételi csoportok", "HomeVideos": "Házi videók", "Inherit": "Inherit", - "ItemAddedWithName": "{0} was added to the library", - "ItemRemovedWithName": "{0} was removed from the library", - "LabelIpAddressValue": "Ip cím: {0}", - "LabelRunningTimeValue": "Running time: {0}", + "ItemAddedWithName": "{0} hozzáadva a könyvtárhoz", + "ItemRemovedWithName": "{0} eltávolítva a könyvtárból", + "LabelIpAddressValue": "IP cím: {0}", + "LabelRunningTimeValue": "Futási idő: {0}", "Latest": "Legújabb", "MessageApplicationUpdated": "Jellyfin Szerver frissítve", - "MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}", + "MessageApplicationUpdatedTo": "Jellyfin Szerver frissítve lett a következőre {0}", "MessageNamedServerConfigurationUpdatedWithValue": "Szerver konfigurációs rész {0} frissítve", "MessageServerConfigurationUpdated": "Szerver konfiguráció frissítve", "MixedContent": "Vegyes tartalom", "Movies": "Filmek", "Music": "Zene", "MusicVideos": "Zenei Videók", - "NameInstallFailed": "{0} installation failed", - "NameSeasonNumber": "Season {0}", - "NameSeasonUnknown": "Season Unknown", - "NewVersionIsAvailable": "A new version of Jellyfin Server is available for download.", - "NotificationOptionApplicationUpdateAvailable": "Program frissítés elérhető", - "NotificationOptionApplicationUpdateInstalled": "Program frissítés telepítve", + "NameInstallFailed": "{0} sikertelen telepítés", + "NameSeasonNumber": "Évad {0}", + "NameSeasonUnknown": "Ismeretlen évad", + "NewVersionIsAvailable": "Letölthető a Jellyfin Szerver új verziója.", + "NotificationOptionApplicationUpdateAvailable": "Új programfrissítés érhető el", + "NotificationOptionApplicationUpdateInstalled": "Programfrissítés telepítve", "NotificationOptionAudioPlayback": "Audió lejátszás elkezdve", "NotificationOptionAudioPlaybackStopped": "Audió lejátszás befejezve", "NotificationOptionCameraImageUploaded": "Kamera kép feltöltve", @@ -57,7 +57,7 @@ "NotificationOptionPluginUninstalled": "Bővítmény eltávolítva", "NotificationOptionPluginUpdateInstalled": "Bővítmény frissítés telepítve", "NotificationOptionServerRestartRequired": "Szerver újraindítás szükséges", - "NotificationOptionTaskFailed": "Scheduled task failure", + "NotificationOptionTaskFailed": "Ütemezett feladat hiba", "NotificationOptionUserLockedOut": "Felhasználó tiltva", "NotificationOptionVideoPlayback": "Videó lejátszás elkezdve", "NotificationOptionVideoPlaybackStopped": "Videó lejátszás befejezve", @@ -68,30 +68,30 @@ "PluginUninstalledWithName": "{0} eltávolítva", "PluginUpdatedWithName": "{0} frissítve", "ProviderValue": "Provider: {0}", - "ScheduledTaskFailedWithName": "{0} failed", - "ScheduledTaskStartedWithName": "{0} started", - "ServerNameNeedsToBeRestarted": "{0} needs to be restarted", + "ScheduledTaskFailedWithName": "{0} hiba", + "ScheduledTaskStartedWithName": "{0} elkezdve", + "ServerNameNeedsToBeRestarted": "{0}-t újra kell indítani", "Shows": "Műsorok", "Songs": "Dalok", - "StartupEmbyServerIsLoading": "Jellyfin Szerver betöltődik. Kérjük, próbáld meg újra később.", + "StartupEmbyServerIsLoading": "A Jellyfin Szerver betöltődik. Kérlek próbáld újra később.", "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", - "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}", + "SubtitlesDownloadedForItem": "Letöltött feliratok a következőhöz {0}", "Sync": "Szinkronizál", "System": "Rendszer", "TvShows": "TV Műsorok", "User": "Felhasználó", - "UserCreatedWithName": "User {0} has been created", - "UserDeletedWithName": "User {0} has been deleted", + "UserCreatedWithName": "{0} felhasználó létrehozva", + "UserDeletedWithName": "{0} felhasználó törölve", "UserDownloadingItemWithValues": "{0} letölti {1}", - "UserLockedOutWithName": "User {0} has been locked out", - "UserOfflineFromDevice": "{0} kijelentkezett innen {1}", - "UserOnlineFromDevice": "{0} is online from {1}", - "UserPasswordChangedWithName": "Password has been changed for user {0}", - "UserPolicyUpdatedWithName": "User policy has been updated for {0}", - "UserStartedPlayingItemWithValues": "{0} elkezdte játszani a következőt {1}", - "UserStoppedPlayingItemWithValues": "{0} befejezte a következőt {1}", - "ValueHasBeenAddedToLibrary": "{0} has been added to your media library", + "UserLockedOutWithName": "{0} felhasználó zárolva van", + "UserOfflineFromDevice": "{0} kijelentkezett innen: {1}", + "UserOnlineFromDevice": "{0} online itt: {1}", + "UserPasswordChangedWithName": "Jelszó megváltozott a következő felhasználó számára: {0}", + "UserPolicyUpdatedWithName": "A felhasználói házirend frissítve lett {0}", + "UserStartedPlayingItemWithValues": "{0} elkezdte játszani a következőt: {1}", + "UserStoppedPlayingItemWithValues": "{0} befejezte a következőt: {1}", + "ValueHasBeenAddedToLibrary": "{0} hozzáadva a médiatárhoz", "ValueSpecialEpisodeName": "Special - {0}", - "VersionNumber": "Verzió {0}" + "VersionNumber": "Verzió: {0}" } From 0302144b220bfe46c158d0241e390c65153196fa Mon Sep 17 00:00:00 2001 From: Kowalski Prime Date: Tue, 5 Feb 2019 13:47:29 +0000 Subject: [PATCH 024/104] Translated using Weblate (Italian) Currently translated at 98.9% (93 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/it/ --- Emby.Server.Implementations/Localization/Core/it.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/it.json b/Emby.Server.Implementations/Localization/Core/it.json index b3d9c16cf2..a5f1e8f94d 100644 --- a/Emby.Server.Implementations/Localization/Core/it.json +++ b/Emby.Server.Implementations/Localization/Core/it.json @@ -5,13 +5,13 @@ "Artists": "Artisti", "AuthenticationSucceededWithUserName": "{0} autenticato con successo", "Books": "Libri", - "CameraImageUploadedFrom": "A new camera image has been uploaded from {0}", + "CameraImageUploadedFrom": "È stata caricata una nuova immagine della fotocamera {0}", "Channels": "Canali", "ChapterNameValue": "Capitolo {0}", "Collections": "Collezioni", "DeviceOfflineWithName": "{0} è stato disconnesso", "DeviceOnlineWithName": "{0} è connesso", - "FailedLoginAttemptWithUserName": "Tentativo di accesso fallito da {0}", + "FailedLoginAttemptWithUserName": "Tentativo di accesso fallito da {0}", "Favorites": "Preferiti", "Folders": "Cartelle", "Genres": "Generi", @@ -19,9 +19,9 @@ "HeaderCameraUploads": "Caricamenti Fotocamera", "HeaderContinueWatching": "Continua a guardare", "HeaderFavoriteAlbums": "Album preferiti", - "HeaderFavoriteArtists": "Artisti preferiti", + "HeaderFavoriteArtists": "Artisti Preferiti", "HeaderFavoriteEpisodes": "Episodi Preferiti", - "HeaderFavoriteShows": "Show preferiti", + "HeaderFavoriteShows": "Serie TV Preferite", "HeaderFavoriteSongs": "Brani Preferiti", "HeaderLiveTV": "Diretta TV", "HeaderNextUp": "Prossimo", From d6b56dde625ab80abbf88bbb9d521c2204a3f9af Mon Sep 17 00:00:00 2001 From: Sarah Zainalabidin Date: Wed, 6 Feb 2019 06:15:40 +0000 Subject: [PATCH 025/104] Translated using Weblate (Malay) Currently translated at 98.9% (93 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ms/ --- Emby.Server.Implementations/Localization/Core/ms.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/ms.json b/Emby.Server.Implementations/Localization/Core/ms.json index c01bb0c501..c10fbe58f6 100644 --- a/Emby.Server.Implementations/Localization/Core/ms.json +++ b/Emby.Server.Implementations/Localization/Core/ms.json @@ -1,10 +1,10 @@ { - "Albums": "Albums", + "Albums": "Album-album", "AppDeviceValues": "App: {0}, Device: {1}", "Application": "Application", - "Artists": "Artists", + "Artists": "Artis-artis", "AuthenticationSucceededWithUserName": "{0} successfully authenticated", - "Books": "Books", + "Books": "Buku-buku", "CameraImageUploadedFrom": "A new camera image has been uploaded from {0}", "Channels": "Channels", "ChapterNameValue": "Chapter {0}", From 87dc60d4aa0d9df5ac3faa0330dd4531d7f823a7 Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Thu, 7 Feb 2019 16:13:21 +0000 Subject: [PATCH 026/104] Translated using Weblate (Dutch) Currently translated at 88.2% (83 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/nl/ --- .../Localization/Core/nl.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/nl.json b/Emby.Server.Implementations/Localization/Core/nl.json index ad6b160473..4bb9e9cfec 100644 --- a/Emby.Server.Implementations/Localization/Core/nl.json +++ b/Emby.Server.Implementations/Localization/Core/nl.json @@ -41,15 +41,15 @@ "Movies": "Films", "Music": "Muziek", "MusicVideos": "Muziekvideo's", - "NameInstallFailed": "{0} installation failed", + "NameInstallFailed": "{0} installatie mislukt", "NameSeasonNumber": "Seizoen {0}", "NameSeasonUnknown": "Seizoen onbekend", - "NewVersionIsAvailable": "A new version of Jellyfin Server is available for download.", + "NewVersionIsAvailable": "Een nieuwe versie van Jellyfin Server is beschikbaar om te downloaden.", "NotificationOptionApplicationUpdateAvailable": "Programma-update beschikbaar", "NotificationOptionApplicationUpdateInstalled": "Programma-update geïnstalleerd", "NotificationOptionAudioPlayback": "Geluid gestart", "NotificationOptionAudioPlaybackStopped": "Geluid gestopt", - "NotificationOptionCameraImageUploaded": "Camera afbeelding geüpload", + "NotificationOptionCameraImageUploaded": "Camera-afbeelding geüpload", "NotificationOptionInstallationFailed": "Installatie mislukt", "NotificationOptionNewLibraryContent": "Nieuwe content toegevoegd", "NotificationOptionPluginError": "Plug-in fout", @@ -70,12 +70,12 @@ "ProviderValue": "Aanbieder: {0}", "ScheduledTaskFailedWithName": "{0} is mislukt", "ScheduledTaskStartedWithName": "{0} is gestart", - "ServerNameNeedsToBeRestarted": "{0} needs to be restarted", + "ServerNameNeedsToBeRestarted": "{0} moet herstart worden", "Shows": "Series", - "Songs": "Titels", + "Songs": "Nummers", "StartupEmbyServerIsLoading": "Jellyfin Server is aan het laden, probeer het later opnieuw.", "SubtitleDownloadFailureForItem": "Downloaden van ondertiteling voor {0} is mislukt", - "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", + "SubtitleDownloadFailureFromForItem": "Ondertitels konden niet gedownload worden van {0} voor {1}", "SubtitlesDownloadedForItem": "Ondertiteling voor {0} is gedownload", "Sync": "Synchronisatie", "System": "Systeem", @@ -89,9 +89,9 @@ "UserOnlineFromDevice": "{0} heeft verbinding met {1}", "UserPasswordChangedWithName": "Wachtwoord voor {0} is gewijzigd", "UserPolicyUpdatedWithName": "Gebruikersbeleid gewijzigd voor {0}", - "UserStartedPlayingItemWithValues": "{0} heeft afspelen van {1} gestart", - "UserStoppedPlayingItemWithValues": "{0} heeft afspelen van {1} gestopt", - "ValueHasBeenAddedToLibrary": "{0} has been added to your media library", + "UserStartedPlayingItemWithValues": "{0} heeft afspelen van {1} gestart op {2}", + "UserStoppedPlayingItemWithValues": "{0} heeft afspelen van {1} gestopt op {2}", + "ValueHasBeenAddedToLibrary": "{0} is toegevoegd aan je mediabibliotheek", "ValueSpecialEpisodeName": "Speciaal - {0}", "VersionNumber": "Versie {0}" } From 0fbdb79df707526fd31b480708de0e07f9b9cb26 Mon Sep 17 00:00:00 2001 From: Stef Havermans Date: Fri, 8 Feb 2019 19:17:22 +0000 Subject: [PATCH 027/104] Translated using Weblate (Dutch) Currently translated at 88.2% (83 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/nl/ --- Emby.Server.Implementations/Localization/Core/nl.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/nl.json b/Emby.Server.Implementations/Localization/Core/nl.json index 4bb9e9cfec..531a9eb441 100644 --- a/Emby.Server.Implementations/Localization/Core/nl.json +++ b/Emby.Server.Implementations/Localization/Core/nl.json @@ -5,7 +5,7 @@ "Artists": "Artiesten", "AuthenticationSucceededWithUserName": "{0} is succesvol geverifieerd", "Books": "Boeken", - "CameraImageUploadedFrom": "A new camera image has been uploaded from {0}", + "CameraImageUploadedFrom": "Er is een nieuwe foto toegevoegd via {0}", "Channels": "Kanalen", "ChapterNameValue": "Hoofdstuk {0}", "Collections": "Collecties", @@ -26,7 +26,7 @@ "HeaderLiveTV": "Live TV", "HeaderNextUp": "Volgende", "HeaderRecordingGroups": "Opnamegroepen", - "HomeVideos": "Thuis video's", + "HomeVideos": "Start video's", "Inherit": "Overerven", "ItemAddedWithName": "{0} is toegevoegd aan de bibliotheek", "ItemRemovedWithName": "{0} is verwijderd uit de bibliotheek", From a4e98a0390a9cd9180af6b9a37f611262d696079 Mon Sep 17 00:00:00 2001 From: Stef Havermans Date: Fri, 8 Feb 2019 19:17:55 +0000 Subject: [PATCH 028/104] Translated using Weblate (Dutch) Currently translated at 97.8% (92 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/nl/ --- Emby.Server.Implementations/Localization/Core/nl.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/nl.json b/Emby.Server.Implementations/Localization/Core/nl.json index 531a9eb441..24af1839fc 100644 --- a/Emby.Server.Implementations/Localization/Core/nl.json +++ b/Emby.Server.Implementations/Localization/Core/nl.json @@ -47,8 +47,8 @@ "NewVersionIsAvailable": "Een nieuwe versie van Jellyfin Server is beschikbaar om te downloaden.", "NotificationOptionApplicationUpdateAvailable": "Programma-update beschikbaar", "NotificationOptionApplicationUpdateInstalled": "Programma-update geïnstalleerd", - "NotificationOptionAudioPlayback": "Geluid gestart", - "NotificationOptionAudioPlaybackStopped": "Geluid gestopt", + "NotificationOptionAudioPlayback": "Muziek gestart", + "NotificationOptionAudioPlaybackStopped": "Muziek gestopt", "NotificationOptionCameraImageUploaded": "Camera-afbeelding geüpload", "NotificationOptionInstallationFailed": "Installatie mislukt", "NotificationOptionNewLibraryContent": "Nieuwe content toegevoegd", From d48275a7854a696bf379d5dc25b31fc7069eda45 Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Thu, 7 Feb 2019 15:51:52 +0000 Subject: [PATCH 029/104] Translated using Weblate (English (United Kingdom)) Currently translated at 97.8% (92 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/en_GB/ --- Emby.Server.Implementations/Localization/Core/en-GB.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Localization/Core/en-GB.json b/Emby.Server.Implementations/Localization/Core/en-GB.json index 3329022925..67d4068cf3 100644 --- a/Emby.Server.Implementations/Localization/Core/en-GB.json +++ b/Emby.Server.Implementations/Localization/Core/en-GB.json @@ -90,7 +90,7 @@ "UserPasswordChangedWithName": "Password has been changed for user {0}", "UserPolicyUpdatedWithName": "User policy has been updated for {0}", "UserStartedPlayingItemWithValues": "{0} has started playing {1}", - "UserStoppedPlayingItemWithValues": "{0} has stopped playing {1}", + "UserStoppedPlayingItemWithValues": "{0} has finished playing {1} on {2}", "ValueHasBeenAddedToLibrary": "{0} has been added to your media library", "ValueSpecialEpisodeName": "Special - {0}", "VersionNumber": "Version {0}" From 982ac324716f9304f2ae713b589e5012821b1783 Mon Sep 17 00:00:00 2001 From: WWWesten Date: Sat, 9 Feb 2019 21:39:49 +0000 Subject: [PATCH 030/104] Translated using Weblate (Russian) Currently translated at 100.0% (94 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ru/ --- Emby.Server.Implementations/Localization/Core/ru.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/ru.json b/Emby.Server.Implementations/Localization/Core/ru.json index d799fa50b5..91fba4bbb1 100644 --- a/Emby.Server.Implementations/Localization/Core/ru.json +++ b/Emby.Server.Implementations/Localization/Core/ru.json @@ -5,7 +5,7 @@ "Artists": "Исполнители", "AuthenticationSucceededWithUserName": "{0} - авторизация успешна", "Books": "Литература", - "CameraImageUploadedFrom": "Новое фото было выложено с {0}", + "CameraImageUploadedFrom": "Новое фото было выложено с камеры {0}", "Channels": "Каналы", "ChapterNameValue": "Сцена {0}", "Collections": "Коллекции", @@ -31,7 +31,7 @@ "ItemAddedWithName": "{0} - добавлено в медиатеку", "ItemRemovedWithName": "{0} - изъято из медиатеки", "LabelIpAddressValue": "IP-адрес: {0}", - "LabelRunningTimeValue": "Время выполнения: {0}", + "LabelRunningTimeValue": "Продолж-ть: {0}", "Latest": "Новейшее", "MessageApplicationUpdated": "Jellyfin Server был обновлён", "MessageApplicationUpdatedTo": "Jellyfin Server был обновлён до {0}", @@ -44,7 +44,7 @@ "NameInstallFailed": "Установка {0} неудачна", "NameSeasonNumber": "Сезон {0}", "NameSeasonUnknown": "Сезон неопознан", - "NewVersionIsAvailable": "Имеется новая версия Jellyfin Server", + "NewVersionIsAvailable": "Имеется для загрузки новая версия Jellyfin Server.", "NotificationOptionApplicationUpdateAvailable": "Имеется обновление приложения", "NotificationOptionApplicationUpdateInstalled": "Обновление приложения установлено", "NotificationOptionAudioPlayback": "Воспр-ие аудио зап-но", @@ -75,7 +75,7 @@ "Songs": "Композиции", "StartupEmbyServerIsLoading": "Jellyfin Server загружается. Повторите попытку в ближайшее время.", "SubtitleDownloadFailureForItem": "Субтитры к {0} не удалось загрузить", - "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", + "SubtitleDownloadFailureFromForItem": "Субтитры к {1} не удалось загрузить с {0}", "SubtitlesDownloadedForItem": "Субтитры к {0} загружены", "Sync": "Синхро", "System": "Система", From 221a95c93c1a50733cfdc79469c01c2786566e83 Mon Sep 17 00:00:00 2001 From: Vasily Date: Mon, 11 Feb 2019 14:59:59 +0000 Subject: [PATCH 031/104] Translated using Weblate (Russian) Currently translated at 100.0% (94 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/ru/ --- Emby.Server.Implementations/Localization/Core/ru.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/ru.json b/Emby.Server.Implementations/Localization/Core/ru.json index 91fba4bbb1..c0465def8d 100644 --- a/Emby.Server.Implementations/Localization/Core/ru.json +++ b/Emby.Server.Implementations/Localization/Core/ru.json @@ -31,20 +31,20 @@ "ItemAddedWithName": "{0} - добавлено в медиатеку", "ItemRemovedWithName": "{0} - изъято из медиатеки", "LabelIpAddressValue": "IP-адрес: {0}", - "LabelRunningTimeValue": "Продолж-ть: {0}", + "LabelRunningTimeValue": "Длительность: {0}", "Latest": "Новейшее", "MessageApplicationUpdated": "Jellyfin Server был обновлён", "MessageApplicationUpdatedTo": "Jellyfin Server был обновлён до {0}", "MessageNamedServerConfigurationUpdatedWithValue": "Конфиг-ия сервера (раздел {0}) была обновлена", "MessageServerConfigurationUpdated": "Конфиг-ия сервера была обновлена", - "MixedContent": "Смешанное содержание", + "MixedContent": "Смешанное содержимое", "Movies": "Кино", "Music": "Музыка", "MusicVideos": "Муз. видео", "NameInstallFailed": "Установка {0} неудачна", "NameSeasonNumber": "Сезон {0}", "NameSeasonUnknown": "Сезон неопознан", - "NewVersionIsAvailable": "Имеется для загрузки новая версия Jellyfin Server.", + "NewVersionIsAvailable": "Новая версия Jellyfin Server доступна для загрузки.", "NotificationOptionApplicationUpdateAvailable": "Имеется обновление приложения", "NotificationOptionApplicationUpdateInstalled": "Обновление приложения установлено", "NotificationOptionAudioPlayback": "Воспр-ие аудио зап-но", From 81a8ebde22e92c9d8f4292bfb18c9134f43bd956 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 3 Feb 2019 17:09:12 +0100 Subject: [PATCH 032/104] Move to Microsoft.Extensions.DependencyInjection This PR replaces SimpleInjector with Microsoft.Extensions.DependencyInjection. --- Emby.Dlna/DlnaManager.cs | 4 +- .../MediaReceiverRegistrar/ControlHandler.cs | 3 +- .../ApplicationHost.cs | 500 +++++------------- .../Emby.Server.Implementations.csproj | 3 +- Jellyfin.Server/Program.cs | 3 +- MediaBrowser.Common/IApplicationHost.cs | 16 +- .../MediaBrowser.Common.csproj | 4 + MediaBrowser.Model/System/PublicSystemInfo.cs | 6 +- MediaBrowser.Model/System/SystemInfo.cs | 3 +- 9 files changed, 152 insertions(+), 390 deletions(-) diff --git a/Emby.Dlna/DlnaManager.cs b/Emby.Dlna/DlnaManager.cs index c507b14e9f..f53d274516 100644 --- a/Emby.Dlna/DlnaManager.cs +++ b/Emby.Dlna/DlnaManager.cs @@ -38,7 +38,9 @@ namespace Emby.Dlna IFileSystem fileSystem, IApplicationPaths appPaths, ILoggerFactory loggerFactory, - IJsonSerializer jsonSerializer, IServerApplicationHost appHost, IAssemblyInfo assemblyInfo) + IJsonSerializer jsonSerializer, + IServerApplicationHost appHost, + IAssemblyInfo assemblyInfo) { _xmlSerializer = xmlSerializer; _fileSystem = fileSystem; diff --git a/Emby.Dlna/MediaReceiverRegistrar/ControlHandler.cs b/Emby.Dlna/MediaReceiverRegistrar/ControlHandler.cs index 6257892b19..ae8175f4a2 100644 --- a/Emby.Dlna/MediaReceiverRegistrar/ControlHandler.cs +++ b/Emby.Dlna/MediaReceiverRegistrar/ControlHandler.cs @@ -36,7 +36,8 @@ namespace Emby.Dlna.MediaReceiverRegistrar }; } - public ControlHandler(IServerConfigurationManager config, ILogger logger, IXmlReaderSettingsFactory xmlReaderSettingsFactory) : base(config, logger, xmlReaderSettingsFactory) + public ControlHandler(IServerConfigurationManager config, ILogger logger, IXmlReaderSettingsFactory xmlReaderSettingsFactory) + : base(config, logger, xmlReaderSettingsFactory) { } } diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index bb475eb2c7..b9d38504c1 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -105,6 +105,7 @@ using MediaBrowser.Providers.Subtitles; using MediaBrowser.WebDashboard.Api; using MediaBrowser.XbmcMetadata.Providers; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.DependencyInjection; using ServiceStack; using ServiceStack.Text.Jsv; using X509Certificate = System.Security.Cryptography.X509Certificates.X509Certificate; @@ -202,7 +203,7 @@ namespace Emby.Server.Implementations /// Gets all concrete types. /// /// All concrete types. - public Tuple[] AllConcreteTypes { get; protected set; } + public Type[] AllConcreteTypes { get; protected set; } /// /// The disposable parts @@ -219,8 +220,6 @@ namespace Emby.Server.Implementations protected IEnvironmentInfo EnvironmentInfo { get; set; } - private IBlurayExaminer BlurayExaminer { get; set; } - public PackageVersionClass SystemUpdateLevel { get @@ -232,12 +231,7 @@ namespace Emby.Server.Implementations } } - public virtual string OperatingSystemDisplayName => EnvironmentInfo.OperatingSystemName; - - /// - /// The container - /// - protected readonly SimpleInjector.Container Container = new SimpleInjector.Container(); + protected IServiceProvider _serviceProvider; /// /// Gets the server configuration manager. @@ -453,138 +447,58 @@ namespace Emby.Server.Implementations /// The name. public string Name => ApplicationProductName; - private static Tuple GetAssembly(Type type) - { - var assembly = type.GetTypeInfo().Assembly; - - return new Tuple(assembly, null); - } - - public virtual IStreamHelper CreateStreamHelper() - { - return new StreamHelper(); - } - /// - /// Creates an instance of type and resolves all constructor dependancies + /// Creates an instance of type and resolves all constructor dependencies /// /// The type. /// System.Object. public object CreateInstance(Type type) - { - return Container.GetInstance(type); - } + => ActivatorUtilities.CreateInstance(_serviceProvider, type); + + /// + /// Creates an instance of type and resolves all constructor dependencies + /// + /// The type. + /// System.Object. + public T CreateInstance() + => ActivatorUtilities.CreateInstance(_serviceProvider); /// /// Creates the instance safe. /// /// The type information. /// System.Object. - protected object CreateInstanceSafe(Tuple typeInfo) + protected object CreateInstanceSafe(Type type) { - var type = typeInfo.Item1; - try { - return Container.GetInstance(type); + return ActivatorUtilities.CreateInstance(_serviceProvider, type); } catch (Exception ex) { - Logger.LogError(ex, "Error creating {type}", type.FullName); + Logger.LogError(ex, "Error creating {Type}", type); // Don't blow up in release mode return null; } } - /// - /// Registers the specified obj. - /// - /// - /// The obj. - /// if set to true [manage lifetime]. - protected void RegisterSingleInstance(T obj, bool manageLifetime = true) - where T : class - { - Container.RegisterInstance(obj); - - if (manageLifetime) - { - var disposable = obj as IDisposable; - - if (disposable != null) - { - DisposableParts.Add(disposable); - } - } - } - - /// - /// Registers the single instance. - /// - /// - /// The func. - protected void RegisterSingleInstance(Func func) - where T : class - { - Container.RegisterSingleton(func); - } - /// /// Resolves this instance. /// /// /// ``0. - public T Resolve() - { - return (T)Container.GetRegistration(typeof(T), true).GetInstance(); - } - - /// - /// Resolves this instance. - /// - /// - /// ``0. - public T TryResolve() - { - var result = Container.GetRegistration(typeof(T), false); - - if (result == null) - { - return default(T); - } - return (T)result.GetInstance(); - } - - /// - /// Loads the assembly. - /// - /// The file. - /// Assembly. - protected Tuple LoadAssembly(string file) - { - try - { - var assembly = Assembly.Load(File.ReadAllBytes(file)); - - return new Tuple(assembly, file); - } - catch (Exception ex) - { - Logger.LogError(ex, "Error loading assembly {File}", file); - return null; - } - } + public T Resolve() => _serviceProvider.GetService(); /// /// Gets the export types. /// /// /// IEnumerable{Type}. - public IEnumerable> GetExportTypes() + public IEnumerable GetExportTypes() { var currentType = typeof(T); - return AllConcreteTypes.Where(i => currentType.IsAssignableFrom(i.Item1)); + return AllConcreteTypes.Where(i => currentType.IsAssignableFrom(i)); } /// @@ -596,7 +510,7 @@ namespace Emby.Server.Implementations public IEnumerable GetExports(bool manageLifetime = true) { var parts = GetExportTypes() - .Select(CreateInstanceSafe) + .Select(x => CreateInstanceSafe(x)) .Where(i => i != null) .Cast(); @@ -611,20 +525,16 @@ namespace Emby.Server.Implementations return parts; } - public List> GetExportsWithInfo(bool manageLifetime = true) + public List<(T, string)> GetExportsWithInfo(bool manageLifetime = true) { var parts = GetExportTypes() .Select(i => { var obj = CreateInstanceSafe(i); - if (obj == null) - { - return null; - } - return new Tuple((T)obj, i.Item2); + return ((T)obj, i.Assembly.Location); }) - .Where(i => i != null) + .Where(i => i.Item1 != null) .ToList(); if (manageLifetime) @@ -691,7 +601,7 @@ namespace Emby.Server.Implementations } } - public async Task Init() + public async Task Init(IServiceCollection serviceCollection) { HttpPort = ServerConfigurationManager.Configuration.HttpServerPortNumber; HttpsPort = ServerConfigurationManager.Configuration.HttpsPortNumber; @@ -721,7 +631,7 @@ namespace Emby.Server.Implementations SetHttpLimit(); - await RegisterResources(); + await RegisterResources(serviceCollection); FindParts(); } @@ -736,104 +646,104 @@ namespace Emby.Server.Implementations /// /// Registers resources that classes will depend on /// - protected async Task RegisterResources() + protected async Task RegisterResources(IServiceCollection serviceCollection) { - RegisterSingleInstance(ConfigurationManager); - RegisterSingleInstance(this); + serviceCollection.AddSingleton(ConfigurationManager); + serviceCollection.AddSingleton(this); - RegisterSingleInstance(ApplicationPaths); + serviceCollection.AddSingleton(ApplicationPaths); - RegisterSingleInstance(JsonSerializer); - RegisterSingleInstance(LoggerFactory, false); - RegisterSingleInstance(Logger); + serviceCollection.AddSingleton(JsonSerializer); - RegisterSingleInstance(EnvironmentInfo); + serviceCollection.AddSingleton(LoggerFactory); + serviceCollection.AddLogging(); + serviceCollection.AddSingleton(Logger); - RegisterSingleInstance(FileSystemManager); + serviceCollection.AddSingleton(EnvironmentInfo); + + serviceCollection.AddSingleton(FileSystemManager); HttpClient = CreateHttpClient(); - RegisterSingleInstance(HttpClient); + serviceCollection.AddSingleton(HttpClient); - RegisterSingleInstance(NetworkManager); + serviceCollection.AddSingleton(NetworkManager); IsoManager = new IsoManager(); - RegisterSingleInstance(IsoManager); + serviceCollection.AddSingleton(IsoManager); TaskManager = new TaskManager(ApplicationPaths, JsonSerializer, LoggerFactory, FileSystemManager); - RegisterSingleInstance(TaskManager); + serviceCollection.AddSingleton(TaskManager); - RegisterSingleInstance(XmlSerializer); + serviceCollection.AddSingleton(XmlSerializer); ProcessFactory = new ProcessFactory(); - RegisterSingleInstance(ProcessFactory); + serviceCollection.AddSingleton(ProcessFactory); - var streamHelper = CreateStreamHelper(); - ApplicationHost.StreamHelper = streamHelper; - RegisterSingleInstance(streamHelper); + ApplicationHost.StreamHelper = new StreamHelper(); + serviceCollection.AddSingleton(StreamHelper); - RegisterSingleInstance(CryptographyProvider); + serviceCollection.AddSingleton(CryptographyProvider); SocketFactory = new SocketFactory(); - RegisterSingleInstance(SocketFactory); + serviceCollection.AddSingleton(SocketFactory); InstallationManager = new InstallationManager(LoggerFactory, this, ApplicationPaths, HttpClient, JsonSerializer, ServerConfigurationManager, FileSystemManager, CryptographyProvider, PackageRuntime); - RegisterSingleInstance(InstallationManager); + serviceCollection.AddSingleton(InstallationManager); ZipClient = new ZipClient(FileSystemManager); - RegisterSingleInstance(ZipClient); + serviceCollection.AddSingleton(ZipClient); HttpResultFactory = new HttpResultFactory(LoggerFactory, FileSystemManager, JsonSerializer, CreateBrotliCompressor()); - RegisterSingleInstance(HttpResultFactory); + serviceCollection.AddSingleton(HttpResultFactory); - RegisterSingleInstance(this); - RegisterSingleInstance(ApplicationPaths); + serviceCollection.AddSingleton(this); + serviceCollection.AddSingleton(ApplicationPaths); - RegisterSingleInstance(ServerConfigurationManager); + serviceCollection.AddSingleton(ServerConfigurationManager); - IAssemblyInfo assemblyInfo = new AssemblyInfo(); - RegisterSingleInstance(assemblyInfo); + var assemblyInfo = new AssemblyInfo(); + serviceCollection.AddSingleton(assemblyInfo); LocalizationManager = new LocalizationManager(ServerConfigurationManager, FileSystemManager, JsonSerializer, LoggerFactory); await LocalizationManager.LoadAll(); - RegisterSingleInstance(LocalizationManager); + serviceCollection.AddSingleton(LocalizationManager); - BlurayExaminer = new BdInfoExaminer(FileSystemManager); - RegisterSingleInstance(BlurayExaminer); + serviceCollection.AddSingleton(new BdInfoExaminer(FileSystemManager)); - RegisterSingleInstance(new XmlReaderSettingsFactory()); + serviceCollection.AddSingleton(new XmlReaderSettingsFactory()); UserDataManager = new UserDataManager(LoggerFactory, ServerConfigurationManager, () => UserManager); - RegisterSingleInstance(UserDataManager); + serviceCollection.AddSingleton(UserDataManager); UserRepository = GetUserRepository(); // This is only needed for disposal purposes. If removing this, make sure to have the manager handle disposing it - RegisterSingleInstance(UserRepository); + serviceCollection.AddSingleton(UserRepository); var displayPreferencesRepo = new SqliteDisplayPreferencesRepository(LoggerFactory, JsonSerializer, ApplicationPaths, FileSystemManager); DisplayPreferencesRepository = displayPreferencesRepo; - RegisterSingleInstance(DisplayPreferencesRepository); + serviceCollection.AddSingleton(DisplayPreferencesRepository); ItemRepository = new SqliteItemRepository(ServerConfigurationManager, this, JsonSerializer, LoggerFactory, assemblyInfo); - RegisterSingleInstance(ItemRepository); + serviceCollection.AddSingleton(ItemRepository); AuthenticationRepository = GetAuthenticationRepository(); - RegisterSingleInstance(AuthenticationRepository); + serviceCollection.AddSingleton(AuthenticationRepository); UserManager = new UserManager(LoggerFactory, ServerConfigurationManager, UserRepository, XmlSerializer, NetworkManager, () => ImageProcessor, () => DtoService, this, JsonSerializer, FileSystemManager, CryptographyProvider); - RegisterSingleInstance(UserManager); + serviceCollection.AddSingleton(UserManager); LibraryManager = new LibraryManager(this, LoggerFactory, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager, () => UserViewManager); - RegisterSingleInstance(LibraryManager); + serviceCollection.AddSingleton(LibraryManager); // TODO wtaylor: investigate use of second music manager var musicManager = new MusicManager(LibraryManager); - RegisterSingleInstance(new MusicManager(LibraryManager)); + serviceCollection.AddSingleton(new MusicManager(LibraryManager)); LibraryMonitor = new LibraryMonitor(LoggerFactory, TaskManager, LibraryManager, ServerConfigurationManager, FileSystemManager, EnvironmentInfo); - RegisterSingleInstance(LibraryMonitor); + serviceCollection.AddSingleton(LibraryMonitor); - RegisterSingleInstance(() => new SearchEngine(LoggerFactory, LibraryManager, UserManager)); + serviceCollection.AddSingleton(new SearchEngine(LoggerFactory, LibraryManager, UserManager)); CertificateInfo = GetCertificateInfo(true); Certificate = GetCertificate(CertificateInfo); @@ -848,81 +758,80 @@ namespace Emby.Server.Implementations GetParseFn); HttpServer.GlobalResponse = LocalizationManager.GetLocalizedString("StartupEmbyServerIsLoading"); - RegisterSingleInstance(HttpServer); + serviceCollection.AddSingleton(HttpServer); ImageProcessor = GetImageProcessor(); - RegisterSingleInstance(ImageProcessor); + serviceCollection.AddSingleton(ImageProcessor); TVSeriesManager = new TVSeriesManager(UserManager, UserDataManager, LibraryManager, ServerConfigurationManager); - RegisterSingleInstance(TVSeriesManager); + serviceCollection.AddSingleton(TVSeriesManager); var encryptionManager = new EncryptionManager(); - RegisterSingleInstance(encryptionManager); + serviceCollection.AddSingleton(encryptionManager); DeviceManager = new DeviceManager(AuthenticationRepository, JsonSerializer, LibraryManager, LocalizationManager, UserManager, FileSystemManager, LibraryMonitor, ServerConfigurationManager, LoggerFactory, NetworkManager); - RegisterSingleInstance(DeviceManager); + serviceCollection.AddSingleton(DeviceManager); MediaSourceManager = new MediaSourceManager(ItemRepository, ApplicationPaths, LocalizationManager, UserManager, LibraryManager, LoggerFactory, JsonSerializer, FileSystemManager, UserDataManager, () => MediaEncoder); - RegisterSingleInstance(MediaSourceManager); + serviceCollection.AddSingleton(MediaSourceManager); SubtitleManager = new SubtitleManager(LoggerFactory, FileSystemManager, LibraryMonitor, MediaSourceManager, LocalizationManager); - RegisterSingleInstance(SubtitleManager); + serviceCollection.AddSingleton(SubtitleManager); ProviderManager = new ProviderManager(HttpClient, SubtitleManager, ServerConfigurationManager, LibraryMonitor, LoggerFactory, FileSystemManager, ApplicationPaths, () => LibraryManager, JsonSerializer); - RegisterSingleInstance(ProviderManager); + serviceCollection.AddSingleton(ProviderManager); DtoService = new DtoService(LoggerFactory, LibraryManager, UserDataManager, ItemRepository, ImageProcessor, ServerConfigurationManager, FileSystemManager, ProviderManager, () => ChannelManager, this, () => DeviceManager, () => MediaSourceManager, () => LiveTvManager); - RegisterSingleInstance(DtoService); + serviceCollection.AddSingleton(DtoService); ChannelManager = new ChannelManager(UserManager, DtoService, LibraryManager, LoggerFactory, ServerConfigurationManager, FileSystemManager, UserDataManager, JsonSerializer, LocalizationManager, HttpClient, ProviderManager); - RegisterSingleInstance(ChannelManager); + serviceCollection.AddSingleton(ChannelManager); SessionManager = new SessionManager(UserDataManager, LoggerFactory, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, JsonSerializer, this, HttpClient, AuthenticationRepository, DeviceManager, MediaSourceManager); - RegisterSingleInstance(SessionManager); + serviceCollection.AddSingleton(SessionManager); - var dlnaManager = new DlnaManager(XmlSerializer, FileSystemManager, ApplicationPaths, LoggerFactory, JsonSerializer, this, assemblyInfo); - RegisterSingleInstance(dlnaManager); + serviceCollection.AddSingleton(new DlnaManager(XmlSerializer, FileSystemManager, ApplicationPaths, LoggerFactory, JsonSerializer, this, assemblyInfo)); CollectionManager = new CollectionManager(LibraryManager, ApplicationPaths, LocalizationManager, FileSystemManager, LibraryMonitor, LoggerFactory, ProviderManager); - RegisterSingleInstance(CollectionManager); + serviceCollection.AddSingleton(CollectionManager); PlaylistManager = new PlaylistManager(LibraryManager, FileSystemManager, LibraryMonitor, LoggerFactory, UserManager, ProviderManager); - RegisterSingleInstance(PlaylistManager); + serviceCollection.AddSingleton(PlaylistManager); LiveTvManager = new LiveTvManager(this, ServerConfigurationManager, LoggerFactory, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager, LocalizationManager, JsonSerializer, FileSystemManager, () => ChannelManager); - RegisterSingleInstance(LiveTvManager); + serviceCollection.AddSingleton(LiveTvManager); UserViewManager = new UserViewManager(LibraryManager, LocalizationManager, UserManager, ChannelManager, LiveTvManager, ServerConfigurationManager); - RegisterSingleInstance(UserViewManager); + serviceCollection.AddSingleton(UserViewManager); NotificationManager = new NotificationManager(LoggerFactory, UserManager, ServerConfigurationManager); - RegisterSingleInstance(NotificationManager); + serviceCollection.AddSingleton(NotificationManager); - RegisterSingleInstance(new DeviceDiscovery(LoggerFactory, ServerConfigurationManager, SocketFactory)); + serviceCollection.AddSingleton(new DeviceDiscovery(LoggerFactory, ServerConfigurationManager, SocketFactory)); ChapterManager = new ChapterManager(LibraryManager, LoggerFactory, ServerConfigurationManager, ItemRepository); - RegisterSingleInstance(ChapterManager); + serviceCollection.AddSingleton(ChapterManager); - RegisterMediaEncoder(assemblyInfo); + RegisterMediaEncoder(serviceCollection); EncodingManager = new MediaEncoder.EncodingManager(FileSystemManager, LoggerFactory, MediaEncoder, ChapterManager, LibraryManager); - RegisterSingleInstance(EncodingManager); + serviceCollection.AddSingleton(EncodingManager); var activityLogRepo = GetActivityLogRepository(); - RegisterSingleInstance(activityLogRepo); - RegisterSingleInstance(new ActivityManager(LoggerFactory, activityLogRepo, UserManager)); + serviceCollection.AddSingleton(activityLogRepo); + serviceCollection.AddSingleton(new ActivityManager(LoggerFactory, activityLogRepo, UserManager)); var authContext = new AuthorizationContext(AuthenticationRepository, UserManager); - RegisterSingleInstance(authContext); - RegisterSingleInstance(new SessionContext(UserManager, authContext, SessionManager)); + serviceCollection.AddSingleton(authContext); + serviceCollection.AddSingleton(new SessionContext(UserManager, authContext, SessionManager)); AuthService = new AuthService(UserManager, authContext, ServerConfigurationManager, SessionManager, NetworkManager); - RegisterSingleInstance(AuthService); + serviceCollection.AddSingleton(AuthService); SubtitleEncoder = new MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder(LibraryManager, LoggerFactory, ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer, HttpClient, MediaSourceManager, ProcessFactory); - RegisterSingleInstance(SubtitleEncoder); + serviceCollection.AddSingleton(SubtitleEncoder); - RegisterSingleInstance(CreateResourceFileManager()); + serviceCollection.AddSingleton(CreateResourceFileManager()); displayPreferencesRepo.Initialize(); @@ -935,6 +844,8 @@ namespace Emby.Server.Implementations ((UserDataManager)UserDataManager).Repository = userDataRepo; ItemRepository.Initialize(userDataRepo, UserManager); ((LibraryManager)LibraryManager).ItemRepository = ItemRepository; + + _serviceProvider = serviceCollection.BuildServiceProvider(); } protected virtual IBrotliCompressor CreateBrotliCompressor() @@ -1066,7 +977,7 @@ namespace Emby.Server.Implementations /// Registers the media encoder. /// /// Task. - private void RegisterMediaEncoder(IAssemblyInfo assemblyInfo) + private void RegisterMediaEncoder(IServiceCollection serviceCollection) { string encoderPath = null; string probePath = null; @@ -1098,7 +1009,7 @@ namespace Emby.Server.Implementations 5000); MediaEncoder = mediaEncoder; - RegisterSingleInstance(MediaEncoder); + serviceCollection.AddSingleton(MediaEncoder); } /// @@ -1208,7 +1119,7 @@ namespace Emby.Server.Implementations IsoManager.AddParts(GetExports()); } - private IPlugin LoadPlugin(Tuple info) + private IPlugin LoadPlugin((IPlugin, string) info) { var plugin = info.Item1; var assemblyFilePath = info.Item2; @@ -1264,78 +1175,15 @@ namespace Emby.Server.Implementations { Logger.LogInformation("Loading assemblies"); - var assemblyInfos = GetComposablePartAssemblies(); - - foreach (var assemblyInfo in assemblyInfos) - { - var assembly = assemblyInfo.Item1; - var path = assemblyInfo.Item2; - - if (path == null) + AllConcreteTypes = GetComposablePartAssemblies() + .SelectMany(x => x.ExportedTypes) + .Where(type => { - Logger.LogInformation("Loading {assemblyName}", assembly.FullName); - } - else - { - Logger.LogInformation("Loading {assemblyName} from {path}", assembly.FullName, path); - } - } - - AllConcreteTypes = assemblyInfos - .SelectMany(GetTypes) - .Where(info => - { - var t = info.Item1; - return t.IsClass && !t.IsAbstract && !t.IsInterface && !t.IsGenericType; + return type.IsClass && !type.IsAbstract && !type.IsInterface && !type.IsGenericType; }) .ToArray(); } - /// - /// Gets a list of types within an assembly - /// This will handle situations that would normally throw an exception - such as a type within the assembly that depends on some other non-existant reference - /// - protected List> GetTypes(Tuple assemblyInfo) - { - if (assemblyInfo == null) - { - return new List>(); - } - - var assembly = assemblyInfo.Item1; - - try - { - // This null checking really shouldn't be needed but adding it due to some - // unhandled exceptions in mono 5.0 that are a little hard to hunt down - var types = assembly.GetTypes() ?? new Type[] { }; - return types.Where(t => t != null).Select(i => new Tuple(i, assemblyInfo.Item2)).ToList(); - } - catch (ReflectionTypeLoadException ex) - { - if (ex.LoaderExceptions != null) - { - foreach (var loaderException in ex.LoaderExceptions) - { - if (loaderException != null) - { - Logger.LogError("LoaderException: " + loaderException.Message); - } - } - } - - // If it fails we can still get a list of the Types it was able to resolve - var types = ex.Types ?? new Type[] { }; - return types.Where(t => t != null).Select(i => new Tuple(i, assemblyInfo.Item2)).ToList(); - } - catch (Exception ex) - { - Logger.LogError(ex, "Error loading types from assembly"); - - return new List>(); - } - } - private CertificateInfo CertificateInfo { get; set; } protected X509Certificate Certificate { get; private set; } @@ -1546,151 +1394,67 @@ namespace Emby.Server.Implementations /// Gets the composable part assemblies. /// /// IEnumerable{Assembly}. - protected List> GetComposablePartAssemblies() + protected IEnumerable GetComposablePartAssemblies() { - var list = GetPluginAssemblies(ApplicationPaths.PluginsPath); + if (Directory.Exists(ApplicationPaths.PluginsPath)) + { + foreach (var file in Directory.EnumerateFiles(ApplicationPaths.PluginsPath, "*.dll", SearchOption.TopDirectoryOnly)) + { + Logger.LogInformation("Loading assembly {Path}", file); + yield return Assembly.LoadFile(file); + } + } // Gets all plugin assemblies by first reading all bytes of the .dll and calling Assembly.Load against that // This will prevent the .dll file from getting locked, and allow us to replace it when needed // Include composable parts in the Api assembly - list.Add(GetAssembly(typeof(ApiEntryPoint))); + yield return typeof(ApiEntryPoint).Assembly; // Include composable parts in the Dashboard assembly - list.Add(GetAssembly(typeof(DashboardService))); + yield return typeof(DashboardService).Assembly; // Include composable parts in the Model assembly - list.Add(GetAssembly(typeof(SystemInfo))); + yield return typeof(SystemInfo).Assembly; // Include composable parts in the Common assembly - list.Add(GetAssembly(typeof(IApplicationHost))); + yield return typeof(IApplicationHost).Assembly; // Include composable parts in the Controller assembly - list.Add(GetAssembly(typeof(IServerApplicationHost))); + yield return typeof(IServerApplicationHost).Assembly; // Include composable parts in the Providers assembly - list.Add(GetAssembly(typeof(ProviderUtils))); + yield return typeof(ProviderUtils).Assembly; // Include composable parts in the Photos assembly - list.Add(GetAssembly(typeof(PhotoProvider))); + yield return typeof(PhotoProvider).Assembly; // Emby.Server implementations - list.Add(GetAssembly(typeof(InstallationManager))); + yield return typeof(InstallationManager).Assembly; // MediaEncoding - list.Add(GetAssembly(typeof(MediaBrowser.MediaEncoding.Encoder.MediaEncoder))); + yield return typeof(MediaBrowser.MediaEncoding.Encoder.MediaEncoder).Assembly; // Dlna - list.Add(GetAssembly(typeof(DlnaEntryPoint))); + yield return typeof(DlnaEntryPoint).Assembly; // Local metadata - list.Add(GetAssembly(typeof(BoxSetXmlSaver))); + yield return typeof(BoxSetXmlSaver).Assembly; // Notifications - list.Add(GetAssembly(typeof(NotificationManager))); + yield return typeof(NotificationManager).Assembly; // Xbmc - list.Add(GetAssembly(typeof(ArtistNfoProvider))); + yield return typeof(ArtistNfoProvider).Assembly; - list.AddRange(GetAssembliesWithPartsInternal().Select(i => new Tuple(i, null))); - - return list.ToList(); + foreach (var i in GetAssembliesWithPartsInternal()) + { + yield return i; + } } protected abstract IEnumerable GetAssembliesWithPartsInternal(); - private List> GetPluginAssemblies(string path) - { - try - { - return FilterAssembliesToLoad(Directory.EnumerateFiles(path, "*.dll", SearchOption.TopDirectoryOnly)) - .Select(LoadAssembly) - .Where(a => a != null) - .ToList(); - } - catch (DirectoryNotFoundException) - { - return new List>(); - } - } - - private IEnumerable FilterAssembliesToLoad(IEnumerable paths) - { - - var exclude = new[] - { - "mbplus.dll", - "mbintros.dll", - "embytv.dll", - "Messenger.dll", - "Messages.dll", - "MediaBrowser.Plugins.TvMazeProvider.dll", - "MBBookshelf.dll", - "MediaBrowser.Channels.Adult.YouJizz.dll", - "MediaBrowser.Channels.Vine-co.dll", - "MediaBrowser.Plugins.Vimeo.dll", - "MediaBrowser.Channels.Vevo.dll", - "MediaBrowser.Plugins.Twitch.dll", - "MediaBrowser.Channels.SvtPlay.dll", - "MediaBrowser.Plugins.SoundCloud.dll", - "MediaBrowser.Plugins.SnesBox.dll", - "MediaBrowser.Plugins.RottenTomatoes.dll", - "MediaBrowser.Plugins.Revision3.dll", - "MediaBrowser.Plugins.NesBox.dll", - "MBChapters.dll", - "MediaBrowser.Channels.LeagueOfLegends.dll", - "MediaBrowser.Plugins.ADEProvider.dll", - "MediaBrowser.Channels.BallStreams.dll", - "MediaBrowser.Channels.Adult.Beeg.dll", - "ChannelDownloader.dll", - "Hamstercat.Emby.EmbyBands.dll", - "EmbyTV.dll", - "MediaBrowser.Channels.HitboxTV.dll", - "MediaBrowser.Channels.HockeyStreams.dll", - "MediaBrowser.Plugins.ITV.dll", - "MediaBrowser.Plugins.Lastfm.dll", - "ServerRestart.dll", - "MediaBrowser.Plugins.NotifyMyAndroidNotifications.dll", - "MetadataViewer.dll" - }; - - var minRequiredVersions = new Dictionary(StringComparer.OrdinalIgnoreCase) - { - { "moviethemesongs.dll", new Version(1, 6) }, - { "themesongs.dll", new Version(1, 2) } - }; - - return paths.Where(path => - { - var filename = Path.GetFileName(path); - if (exclude.Contains(filename ?? string.Empty, StringComparer.OrdinalIgnoreCase)) - { - return false; - } - - if (minRequiredVersions.TryGetValue(filename, out Version minRequiredVersion)) - { - try - { - var version = Version.Parse(FileVersionInfo.GetVersionInfo(path).FileVersion); - - if (version < minRequiredVersion) - { - Logger.LogInformation("Not loading {filename} {version} because the minimum supported version is {minRequiredVersion}. Please update to the newer version", filename, version, minRequiredVersion); - return false; - } - } - catch (Exception ex) - { - Logger.LogError(ex, "Error getting version number from {path}", path); - - return false; - } - } - return true; - }); - } - /// /// Gets the system status. /// @@ -1718,7 +1482,7 @@ namespace Emby.Server.Implementations SupportsHttps = SupportsHttps, HttpsPortNumber = HttpsPort, OperatingSystem = EnvironmentInfo.OperatingSystem.ToString(), - OperatingSystemDisplayName = OperatingSystemDisplayName, + OperatingSystemDisplayName = EnvironmentInfo.OperatingSystemName, CanSelfRestart = CanSelfRestart, CanSelfUpdate = CanSelfUpdate, CanLaunchWebBrowser = CanLaunchWebBrowser, @@ -1788,7 +1552,7 @@ namespace Emby.Server.Implementations public async Task GetWanApiUrl(CancellationToken cancellationToken) { - var url = "http://ipv4.icanhazip.com"; + const string url = "http://ipv4.icanhazip.com"; try { using (var response = await HttpClient.Get(new HttpRequestOptions diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 8356a9501b..6bf776f533 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -22,9 +22,10 @@ + + - diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 7826fde35b..2e6226b228 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -21,6 +21,7 @@ using MediaBrowser.Controller.Drawing; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Serilog; using Serilog.AspNetCore; @@ -114,7 +115,7 @@ namespace Jellyfin.Server new NullImageEncoder(), new NetworkManager(_loggerFactory, environmentInfo))) { - await appHost.Init(); + await appHost.Init(new ServiceCollection()); appHost.ImageProcessor.ImageEncoder = GetImageEncoder(fileSystem, appPaths, appHost.LocalizationManager); diff --git a/MediaBrowser.Common/IApplicationHost.cs b/MediaBrowser.Common/IApplicationHost.cs index 59e3c17674..6891152ee2 100644 --- a/MediaBrowser.Common/IApplicationHost.cs +++ b/MediaBrowser.Common/IApplicationHost.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using MediaBrowser.Common.Plugins; using MediaBrowser.Model.Events; using MediaBrowser.Model.Updates; +using Microsoft.Extensions.DependencyInjection; namespace MediaBrowser.Common { @@ -13,12 +14,6 @@ namespace MediaBrowser.Common /// public interface IApplicationHost { - /// - /// Gets the display name of the operating system. - /// - /// The display name of the operating system. - string OperatingSystemDisplayName { get; } - /// /// Gets the name. /// @@ -104,13 +99,6 @@ namespace MediaBrowser.Common /// ``0. T Resolve(); - /// - /// Resolves this instance. - /// - /// - /// ``0. - T TryResolve(); - /// /// Shuts down. /// @@ -131,7 +119,7 @@ namespace MediaBrowser.Common /// /// Inits this instance. /// - Task Init(); + Task Init(IServiceCollection serviceCollection); /// /// Creates the instance. diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 2220d46610..715f4fccd3 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -11,6 +11,10 @@ + + + + diff --git a/MediaBrowser.Model/System/PublicSystemInfo.cs b/MediaBrowser.Model/System/PublicSystemInfo.cs index accdc9e601..d97eda3523 100644 --- a/MediaBrowser.Model/System/PublicSystemInfo.cs +++ b/MediaBrowser.Model/System/PublicSystemInfo.cs @@ -24,12 +24,12 @@ namespace MediaBrowser.Model.System /// Gets or sets the server version. /// /// The version. - public string Version { get; set; } + public string Version { get; set; } /// - /// Gets or sets the operating sytem. + /// Gets or sets the operating system. /// - /// The operating sytem. + /// The operating system. public string OperatingSystem { get; set; } /// diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index 26f7353307..d9ed68b27e 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -1,3 +1,4 @@ +using System; using System.Runtime.InteropServices; using MediaBrowser.Model.Updates; @@ -136,7 +137,7 @@ namespace MediaBrowser.Model.System /// public SystemInfo() { - CompletedInstallations = new InstallationInfo[] { }; + CompletedInstallations = Array.Empty(); } } } From 9af28607c990f5ddcd738c72d7183b9a57ba47c2 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 6 Feb 2019 14:04:32 +0100 Subject: [PATCH 033/104] Simplify plugin loading --- .../ApplicationHost.cs | 45 +++++-------------- Jellyfin.Server/CoreAppHost.cs | 4 +- 2 files changed, 13 insertions(+), 36 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index b9d38504c1..5dcf42aae9 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -303,7 +303,6 @@ namespace Emby.Server.Implementations /// The user data repository. private IUserDataManager UserDataManager { get; set; } private IUserRepository UserRepository { get; set; } - internal IDisplayPreferencesRepository DisplayPreferencesRepository { get; set; } internal SqliteItemRepository ItemRepository { get; set; } private INotificationManager NotificationManager { get; set; } @@ -472,6 +471,7 @@ namespace Emby.Server.Implementations { try { + Logger.LogWarning("Creating instance of {Type}", type); return ActivatorUtilities.CreateInstance(_serviceProvider, type); } catch (Exception ex) @@ -525,29 +525,6 @@ namespace Emby.Server.Implementations return parts; } - public List<(T, string)> GetExportsWithInfo(bool manageLifetime = true) - { - var parts = GetExportTypes() - .Select(i => - { - var obj = CreateInstanceSafe(i); - - return ((T)obj, i.Assembly.Location); - }) - .Where(i => i.Item1 != null) - .ToList(); - - if (manageLifetime) - { - lock (DisposableParts) - { - DisposableParts.AddRange(parts.Select(i => i.Item1).OfType()); - } - } - - return parts; - } - /// /// Runs the startup tasks. /// @@ -721,8 +698,7 @@ namespace Emby.Server.Implementations serviceCollection.AddSingleton(UserRepository); var displayPreferencesRepo = new SqliteDisplayPreferencesRepository(LoggerFactory, JsonSerializer, ApplicationPaths, FileSystemManager); - DisplayPreferencesRepository = displayPreferencesRepo; - serviceCollection.AddSingleton(DisplayPreferencesRepository); + serviceCollection.AddSingleton(displayPreferencesRepo); ItemRepository = new SqliteItemRepository(ServerConfigurationManager, this, JsonSerializer, LoggerFactory, assemblyInfo); serviceCollection.AddSingleton(ItemRepository); @@ -1085,7 +1061,10 @@ namespace Emby.Server.Implementations } ConfigurationManager.AddParts(GetExports()); - Plugins = GetExportsWithInfo().Select(LoadPlugin).Where(i => i != null).ToArray(); + Plugins = GetExports() + .Select(LoadPlugin) + .Where(i => i != null) + .ToArray(); HttpServer.Init(GetExports(false), GetExports()); @@ -1119,19 +1098,15 @@ namespace Emby.Server.Implementations IsoManager.AddParts(GetExports()); } - private IPlugin LoadPlugin((IPlugin, string) info) + private IPlugin LoadPlugin(IPlugin plugin) { - var plugin = info.Item1; - var assemblyFilePath = info.Item2; - try { - var assemblyPlugin = plugin as IPluginAssembly; - - if (assemblyPlugin != null) + if (plugin is IPluginAssembly assemblyPlugin) { var assembly = plugin.GetType().Assembly; var assemblyName = assembly.GetName(); + var assemblyFilePath = assembly.Location; var dataFolderPath = Path.Combine(ApplicationPaths.PluginsPath, Path.GetFileNameWithoutExtension(assemblyFilePath)); @@ -1401,7 +1376,7 @@ namespace Emby.Server.Implementations foreach (var file in Directory.EnumerateFiles(ApplicationPaths.PluginsPath, "*.dll", SearchOption.TopDirectoryOnly)) { Logger.LogInformation("Loading assembly {Path}", file); - yield return Assembly.LoadFile(file); + yield return Assembly.LoadFrom(file); } } diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index 315e34a04c..a486c2a475 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -21,7 +21,9 @@ namespace Jellyfin.Server protected override void RestartInternal() => Program.Restart(); protected override IEnumerable GetAssembliesWithPartsInternal() - => new[] { typeof(CoreAppHost).Assembly }; + { + yield return typeof(CoreAppHost).Assembly; + } protected override void ShutdownInternal() => Program.Shutdown(); From d409623086e210d9256ce0863f6fb8dad57e69ef Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 6 Feb 2019 17:41:38 +0100 Subject: [PATCH 034/104] Don't create multiple instances of the same type --- Emby.Server.Implementations/ApplicationHost.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 5dcf42aae9..41ac4fcffa 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -512,7 +512,8 @@ namespace Emby.Server.Implementations var parts = GetExportTypes() .Select(x => CreateInstanceSafe(x)) .Where(i => i != null) - .Cast(); + .Cast() + .ToList(); // Convert to list so this isn't executed for each iteration if (manageLifetime) { From 64d5ec12e260758c4a7b3e9df85212b51dab8444 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 8 Feb 2019 22:59:28 +0100 Subject: [PATCH 035/104] Use HashSets for increased perf --- .../Data/BaseSqliteRepository.cs | 10 +- .../Data/SqliteItemRepository.cs | 183 +++++++++--------- .../Library/LibraryManager.cs | 20 +- .../Library/UserManager.cs | 4 +- MediaBrowser.Api/BaseApiService.cs | 32 ++- MediaBrowser.Api/UserLibrary/ItemsService.cs | 9 +- 6 files changed, 128 insertions(+), 130 deletions(-) diff --git a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs index 0f432c36c0..a6be0da587 100644 --- a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs +++ b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs @@ -375,21 +375,15 @@ namespace Emby.Server.Implementations.Data } } - public class DummyToken : IDisposable - { - public void Dispose() - { - } - } - public static IDisposable Read(this ReaderWriterLockSlim obj) { //if (BaseSqliteRepository.ThreadSafeMode > 0) //{ // return new DummyToken(); //} - return new WriteLockToken(obj); + return new ReadLockToken(obj); } + public static IDisposable Write(this ReaderWriterLockSlim obj) { //if (BaseSqliteRepository.ThreadSafeMode > 0) diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 3014e482df..a0abd6ea0d 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -1183,9 +1183,9 @@ namespace Emby.Server.Implementations.Data /// public BaseItem RetrieveItem(Guid id) { - if (id.Equals(Guid.Empty)) + if (id == Guid.Empty) { - throw new ArgumentNullException(nameof(id)); + throw new ArgumentException(nameof(id), "Guid can't be empty"); } CheckDisposed(); @@ -2079,14 +2079,14 @@ namespace Emby.Server.Implementations.Data return false; } - var sortingFields = query.OrderBy.Select(i => i.Item1); + var sortingFields = new HashSet(query.OrderBy.Select(i => i.Item1), StringComparer.OrdinalIgnoreCase); - return sortingFields.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase) - || sortingFields.Contains(ItemSortBy.IsPlayed, StringComparer.OrdinalIgnoreCase) - || sortingFields.Contains(ItemSortBy.IsUnplayed, StringComparer.OrdinalIgnoreCase) - || sortingFields.Contains(ItemSortBy.PlayCount, StringComparer.OrdinalIgnoreCase) - || sortingFields.Contains(ItemSortBy.DatePlayed, StringComparer.OrdinalIgnoreCase) - || sortingFields.Contains(ItemSortBy.SeriesDatePlayed, StringComparer.OrdinalIgnoreCase) + return sortingFields.Contains(ItemSortBy.IsFavoriteOrLiked) + || sortingFields.Contains(ItemSortBy.IsPlayed) + || sortingFields.Contains(ItemSortBy.IsUnplayed) + || sortingFields.Contains(ItemSortBy.PlayCount) + || sortingFields.Contains(ItemSortBy.DatePlayed) + || sortingFields.Contains(ItemSortBy.SeriesDatePlayed) || query.IsFavoriteOrLiked.HasValue || query.IsFavorite.HasValue || query.IsResumable.HasValue @@ -2151,18 +2151,26 @@ namespace Emby.Server.Implementations.Data } } + private static readonly HashSet _programExcludeParentTypes = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "Series", + "Season", + "MusicAlbum", + "MusicArtist", + "PhotoAlbum" + }; + + private static readonly HashSet _programTypes = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "Program", + "TvChannel", + "LiveTvProgram", + "LiveTvTvChannel" + }; + private bool HasProgramAttributes(InternalItemsQuery query) { - var excludeParentTypes = new string[] - { - "Series", - "Season", - "MusicAlbum", - "MusicArtist", - "PhotoAlbum" - }; - - if (excludeParentTypes.Contains(query.ParentType ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + if (_programExcludeParentTypes.Contains(query.ParentType)) { return false; } @@ -2172,29 +2180,18 @@ namespace Emby.Server.Implementations.Data return true; } - var types = new string[] - { - "Program", - "TvChannel", - "LiveTvProgram", - "LiveTvTvChannel" - }; - - return types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase)); + return query.IncludeItemTypes.Any(x => _programTypes.Contains(x)); } + private static readonly HashSet _serviceTypes = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "TvChannel", + "LiveTvTvChannel" + }; + private bool HasServiceName(InternalItemsQuery query) { - var excludeParentTypes = new string[] - { - "Series", - "Season", - "MusicAlbum", - "MusicArtist", - "PhotoAlbum" - }; - - if (excludeParentTypes.Contains(query.ParentType ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + if (_programExcludeParentTypes.Contains(query.ParentType)) { return false; } @@ -2204,27 +2201,18 @@ namespace Emby.Server.Implementations.Data return true; } - var types = new string[] - { - "TvChannel", - "LiveTvTvChannel" - }; - - return types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase)); + return query.IncludeItemTypes.Any(x => _serviceTypes.Contains(x)); } + private static readonly HashSet _startDateTypes = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "Program", + "LiveTvProgram" + }; + private bool HasStartDate(InternalItemsQuery query) { - var excludeParentTypes = new string[] - { - "Series", - "Season", - "MusicAlbum", - "MusicArtist", - "PhotoAlbum" - }; - - if (excludeParentTypes.Contains(query.ParentType ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + if (_programExcludeParentTypes.Contains(query.ParentType)) { return false; } @@ -2234,13 +2222,7 @@ namespace Emby.Server.Implementations.Data return true; } - var types = new string[] - { - "Program", - "LiveTvProgram" - }; - - return types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase)); + return query.IncludeItemTypes.Any(x => _startDateTypes.Contains(x)); } private bool HasEpisodeAttributes(InternalItemsQuery query) @@ -2263,16 +2245,26 @@ namespace Emby.Server.Implementations.Data return query.IncludeItemTypes.Contains("Trailer", StringComparer.OrdinalIgnoreCase); } + + private static readonly HashSet _artistExcludeParentTypes = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "Series", + "Season", + "PhotoAlbum" + }; + + private static readonly HashSet _artistsTypes = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "Audio", + "MusicAlbum", + "MusicVideo", + "AudioBook", + "AudioPodcast" + }; + private bool HasArtistFields(InternalItemsQuery query) { - var excludeParentTypes = new string[] - { - "Series", - "Season", - "PhotoAlbum" - }; - - if (excludeParentTypes.Contains(query.ParentType ?? string.Empty, StringComparer.OrdinalIgnoreCase)) + if (_artistExcludeParentTypes.Contains(query.ParentType)) { return false; } @@ -2282,18 +2274,18 @@ namespace Emby.Server.Implementations.Data return true; } - var types = new string[] - { - "Audio", - "MusicAlbum", - "MusicVideo", - "AudioBook", - "AudioPodcast" - }; - - return types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase)); + return query.IncludeItemTypes.Any(x => _artistsTypes.Contains(x)); } + private static readonly HashSet _seriesTypes = new HashSet(StringComparer.OrdinalIgnoreCase) + { + "Audio", + "MusicAlbum", + "MusicVideo", + "AudioBook", + "AudioPodcast" + }; + private bool HasSeriesFields(InternalItemsQuery query) { if (string.Equals(query.ParentType, "PhotoAlbum", StringComparison.OrdinalIgnoreCase)) @@ -2306,15 +2298,7 @@ namespace Emby.Server.Implementations.Data return true; } - var types = new string[] - { - "Book", - "AudioBook", - "Episode", - "Season" - }; - - return types.Any(i => query.IncludeItemTypes.Contains(i, StringComparer.OrdinalIgnoreCase)); + return query.IncludeItemTypes.Any(x => _seriesTypes.Contains(x)); } private string[] GetFinalColumnsToSelect(InternalItemsQuery query, string[] startColumns) @@ -2325,7 +2309,7 @@ namespace Emby.Server.Implementations.Data { if (!HasField(query, field)) { - foreach (var fieldToRemove in GetColumnNamesFromField(field).ToList()) + foreach (var fieldToRemove in GetColumnNamesFromField(field)) { list.Remove(fieldToRemove); } @@ -2419,11 +2403,14 @@ namespace Emby.Server.Implementations.Data list.Add(builder.ToString()); - var excludeIds = query.ExcludeItemIds.ToList(); - excludeIds.Add(item.Id); - excludeIds.AddRange(item.ExtraIds); + var oldLen = query.ExcludeItemIds.Length; + var newLen = oldLen + item.ExtraIds.Length + 1; + var excludeIds = new Guid[newLen]; + query.ExcludeItemIds.CopyTo(excludeIds, 0); + excludeIds[oldLen] = item.Id; + item.ExtraIds.CopyTo(excludeIds, oldLen + 1); - query.ExcludeItemIds = excludeIds.ToArray(); + query.ExcludeItemIds = excludeIds; query.ExcludeProviderIds = item.ProviderIds; } @@ -2735,6 +2722,7 @@ namespace Emby.Server.Implementations.Data { continue; } + if (item.GetProviderId(providerId.Key) == providerId.Value) { if (newItem.SourceType == SourceType.Library) @@ -4952,7 +4940,12 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type return result; } - return new[] { value }.Where(IsValidType); + if (IsValidType(value)) + { + return new[] { value }; + } + + return Array.Empty(); } public void DeleteItem(Guid id, CancellationToken cancellationToken) diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 064006ebd6..6218d3a086 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -1225,9 +1225,9 @@ namespace Emby.Server.Implementations.Library /// id public BaseItem GetItemById(Guid id) { - if (id.Equals(Guid.Empty)) + if (id == Guid.Empty) { - throw new ArgumentNullException(nameof(id)); + throw new ArgumentException(nameof(id), "Guid can't be empty"); } if (LibraryItemsCache.TryGetValue(id, out BaseItem item)) @@ -1237,8 +1237,6 @@ namespace Emby.Server.Implementations.Library item = RetrieveItem(id); - //_logger.LogDebug("GetitemById {0}", id); - if (item != null) { RegisterItem(item); @@ -2005,9 +2003,7 @@ namespace Emby.Server.Implementations.Library .FirstOrDefault(); } - var options = collectionFolder == null ? new LibraryOptions() : collectionFolder.GetLibraryOptions(); - - return options; + return collectionFolder == null ? new LibraryOptions() : collectionFolder.GetLibraryOptions(); } public string GetContentType(BaseItem item) @@ -2017,11 +2013,13 @@ namespace Emby.Server.Implementations.Library { return configuredContentType; } + configuredContentType = GetConfiguredContentType(item, true); if (!string.IsNullOrEmpty(configuredContentType)) { return configuredContentType; } + return GetInheritedContentType(item); } @@ -2056,6 +2054,7 @@ namespace Emby.Server.Implementations.Library { return collectionFolder.CollectionType; } + return GetContentTypeOverride(item.ContainingFolderPath, inheritConfiguredPath); } @@ -2066,6 +2065,7 @@ namespace Emby.Server.Implementations.Library { return nameValuePair.Value; } + return null; } @@ -2108,9 +2108,9 @@ namespace Emby.Server.Implementations.Library string viewType, string sortName) { - var path = Path.Combine(ConfigurationManager.ApplicationPaths.InternalMetadataPath, "views"); - - path = Path.Combine(path, _fileSystem.GetValidFilename(viewType)); + var path = Path.Combine(ConfigurationManager.ApplicationPaths.InternalMetadataPath, + "views", + _fileSystem.GetValidFilename(viewType)); var id = GetNewItemId(path + "_namedview_" + name, typeof(UserView)); diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs index 3ff84382f2..22a593d494 100644 --- a/Emby.Server.Implementations/Library/UserManager.cs +++ b/Emby.Server.Implementations/Library/UserManager.cs @@ -171,9 +171,9 @@ namespace Emby.Server.Implementations.Library /// public User GetUserById(Guid id) { - if (id.Equals(Guid.Empty)) + if (id == Guid.Empty) { - throw new ArgumentNullException(nameof(id)); + throw new ArgumentException(nameof(id), "Guid can't be empty"); } return Users.FirstOrDefault(u => u.Id == id); diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs index 451ee72dd9..a037357ede 100644 --- a/MediaBrowser.Api/BaseApiService.cs +++ b/MediaBrowser.Api/BaseApiService.cs @@ -9,6 +9,7 @@ using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Services; +using MediaBrowser.Model.Querying; using Microsoft.Extensions.Logging; namespace MediaBrowser.Api @@ -118,8 +119,7 @@ namespace MediaBrowser.Api { var options = new DtoOptions(); - var hasFields = request as IHasItemFields; - if (hasFields != null) + if (request is IHasItemFields hasFields) { options.Fields = hasFields.GetItemFields(); } @@ -133,9 +133,11 @@ namespace MediaBrowser.Api client.IndexOf("media center", StringComparison.OrdinalIgnoreCase) != -1 || client.IndexOf("classic", StringComparison.OrdinalIgnoreCase) != -1) { - var list = options.Fields.ToList(); - list.Add(Model.Querying.ItemFields.RecursiveItemCount); - options.Fields = list.ToArray(); + int oldLen = options.Fields.Length; + var arr = new ItemFields[oldLen + 1]; + options.Fields.CopyTo(arr, 0); + arr[oldLen] = Model.Querying.ItemFields.RecursiveItemCount; + options.Fields = arr; } if (client.IndexOf("kodi", StringComparison.OrdinalIgnoreCase) != -1 || @@ -146,9 +148,12 @@ namespace MediaBrowser.Api client.IndexOf("samsung", StringComparison.OrdinalIgnoreCase) != -1 || client.IndexOf("androidtv", StringComparison.OrdinalIgnoreCase) != -1) { - var list = options.Fields.ToList(); - list.Add(Model.Querying.ItemFields.ChildCount); - options.Fields = list.ToArray(); + + int oldLen = options.Fields.Length; + var arr = new ItemFields[oldLen + 1]; + options.Fields.CopyTo(arr, 0); + arr[oldLen] = Model.Querying.ItemFields.ChildCount; + options.Fields = arr; } } @@ -167,7 +172,16 @@ namespace MediaBrowser.Api if (!string.IsNullOrWhiteSpace(hasDtoOptions.EnableImageTypes)) { - options.ImageTypes = (hasDtoOptions.EnableImageTypes ?? string.Empty).Split(',').Where(i => !string.IsNullOrWhiteSpace(i)).Select(v => (ImageType)Enum.Parse(typeof(ImageType), v, true)).ToArray(); + if (string.IsNullOrEmpty(hasDtoOptions.EnableImageTypes)) + { + options.ImageTypes = Array.Empty(); + } + else + { + options.ImageTypes = hasDtoOptions.EnableImageTypes.Split(new [] { ',' }, StringSplitOptions.RemoveEmptyEntries) + .Select(v => (ImageType)Enum.Parse(typeof(ImageType), v, true)) + .ToArray(); + } } } diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index 3ae7da0073..46d7c250e8 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -155,7 +155,7 @@ namespace MediaBrowser.Api.UserLibrary /// The request. private QueryResult GetItems(GetItems request) { - var user = !request.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(request.UserId) : null; + var user = request.UserId == Guid.Empty ? null : _userManager.GetUserById(request.UserId); var dtoOptions = GetDtoOptions(_authContext, request); @@ -190,11 +190,8 @@ namespace MediaBrowser.Api.UserLibrary /// private QueryResult GetQueryResult(GetItems request, DtoOptions dtoOptions, User user) { - if (string.Equals(request.IncludeItemTypes, "Playlist", StringComparison.OrdinalIgnoreCase)) - { - request.ParentId = null; - } - else if (string.Equals(request.IncludeItemTypes, "BoxSet", StringComparison.OrdinalIgnoreCase)) + if (string.Equals(request.IncludeItemTypes, "Playlist", StringComparison.OrdinalIgnoreCase) + || string.Equals(request.IncludeItemTypes, "BoxSet", StringComparison.OrdinalIgnoreCase)) { request.ParentId = null; } From 41fb1e510616e42490354b8912d2117b836ab822 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 9 Feb 2019 00:48:09 +0100 Subject: [PATCH 036/104] Tuple -> ValueTuple --- .../Data/BaseSqliteRepository.cs | 21 ++--------- .../Data/SqliteItemRepository.cs | 35 ++++++++----------- .../Library/LibraryManager.cs | 12 +++---- Jellyfin.Server/Jellyfin.Server.csproj | 2 +- .../UserLibrary/ArtistsService.cs | 2 +- .../UserLibrary/BaseItemsByNameService.cs | 4 +-- MediaBrowser.Api/UserLibrary/GenresService.cs | 2 +- .../UserLibrary/MusicGenresService.cs | 2 +- .../UserLibrary/PersonsService.cs | 6 ++-- .../UserLibrary/StudiosService.cs | 2 +- .../Library/ILibraryManager.cs | 12 +++---- .../Persistence/IItemRepository.cs | 12 +++---- 12 files changed, 45 insertions(+), 67 deletions(-) diff --git a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs index a6be0da587..556b7a547d 100644 --- a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs +++ b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs @@ -224,7 +224,7 @@ namespace Emby.Server.Implementations.Data }); } - db.ExecuteAll(string.Join(";", queries.ToArray())); + db.ExecuteAll(string.Join(";", queries)); Logger.LogInformation("PRAGMA synchronous=" + db.Query("PRAGMA synchronous").SelectScalarString().First()); } @@ -232,23 +232,6 @@ namespace Emby.Server.Implementations.Data protected virtual int? CacheSize => null; - internal static void CheckOk(int rc) - { - string msg = ""; - - if (raw.SQLITE_OK != rc) - { - throw CreateException((ErrorCode)rc, msg); - } - } - - internal static Exception CreateException(ErrorCode rc, string msg) - { - var exp = new Exception(msg); - - return exp; - } - private bool _disposed; protected void CheckDisposed() { @@ -381,7 +364,7 @@ namespace Emby.Server.Implementations.Data //{ // return new DummyToken(); //} - return new ReadLockToken(obj); + return new WriteLockToken(obj); // TODO: fix segfault } public static IDisposable Write(this ReaderWriterLockSlim obj) diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index a0abd6ea0d..6a346f31f6 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -2301,7 +2301,7 @@ namespace Emby.Server.Implementations.Data return query.IncludeItemTypes.Any(x => _seriesTypes.Contains(x)); } - private string[] GetFinalColumnsToSelect(InternalItemsQuery query, string[] startColumns) + private List GetFinalColumnsToSelect(InternalItemsQuery query, IEnumerable startColumns) { var list = startColumns.ToList(); @@ -2431,7 +2431,7 @@ namespace Emby.Server.Implementations.Data list.Add(builder.ToString()); } - return list.ToArray(); + return list; } private void BindSearchParams(InternalItemsQuery query, IStatement statement) @@ -5208,32 +5208,32 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type } } - public QueryResult> GetAllArtists(InternalItemsQuery query) + public QueryResult<(BaseItem, ItemCounts)> GetAllArtists(InternalItemsQuery query) { return GetItemValues(query, new[] { 0, 1 }, typeof(MusicArtist).FullName); } - public QueryResult> GetArtists(InternalItemsQuery query) + public QueryResult<(BaseItem, ItemCounts)> GetArtists(InternalItemsQuery query) { return GetItemValues(query, new[] { 0 }, typeof(MusicArtist).FullName); } - public QueryResult> GetAlbumArtists(InternalItemsQuery query) + public QueryResult<(BaseItem, ItemCounts)> GetAlbumArtists(InternalItemsQuery query) { return GetItemValues(query, new[] { 1 }, typeof(MusicArtist).FullName); } - public QueryResult> GetStudios(InternalItemsQuery query) + public QueryResult<(BaseItem, ItemCounts)> GetStudios(InternalItemsQuery query) { return GetItemValues(query, new[] { 3 }, typeof(Studio).FullName); } - public QueryResult> GetGenres(InternalItemsQuery query) + public QueryResult<(BaseItem, ItemCounts)> GetGenres(InternalItemsQuery query) { return GetItemValues(query, new[] { 2 }, typeof(Genre).FullName); } - public QueryResult> GetMusicGenres(InternalItemsQuery query) + public QueryResult<(BaseItem, ItemCounts)> GetMusicGenres(InternalItemsQuery query) { return GetItemValues(query, new[] { 2 }, typeof(MusicGenre).FullName); } @@ -5310,7 +5310,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type } } - private QueryResult> GetItemValues(InternalItemsQuery query, int[] itemValueTypes, string returnType) + private QueryResult<(BaseItem, ItemCounts)> GetItemValues(InternalItemsQuery query, int[] itemValueTypes, string returnType) { if (query == null) { @@ -5328,7 +5328,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type var typeClause = itemValueTypes.Length == 1 ? ("Type=" + itemValueTypes[0].ToString(CultureInfo.InvariantCulture)) : - ("Type in (" + string.Join(",", itemValueTypes.Select(i => i.ToString(CultureInfo.InvariantCulture)).ToArray()) + ")"); + ("Type in (" + string.Join(",", itemValueTypes.Select(i => i.ToString(CultureInfo.InvariantCulture))) + ")"); InternalItemsQuery typeSubQuery = null; @@ -5356,11 +5356,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type whereClauses.Add("guid in (select ItemId from ItemValues where ItemValues.CleanValue=A.CleanName AND " + typeClause + ")"); - var typeWhereText = whereClauses.Count == 0 ? - string.Empty : - " where " + string.Join(" AND ", whereClauses); - - itemCountColumnQuery += typeWhereText; + itemCountColumnQuery += " where " + string.Join(" AND ", whereClauses); itemCountColumns = new Dictionary() { @@ -5393,7 +5389,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type IsSeries = query.IsSeries }; - columns = GetFinalColumnsToSelect(query, columns.ToArray()).ToList(); + columns = GetFinalColumnsToSelect(query, columns); var commandText = "select " + string.Join(",", columns) @@ -5485,8 +5481,8 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type { return connection.RunInTransaction(db => { - var list = new List>(); - var result = new QueryResult>(); + var list = new List<(BaseItem, ItemCounts)>(); + var result = new QueryResult<(BaseItem, ItemCounts)>(); var statements = PrepareAllSafe(db, statementTexts); @@ -5524,7 +5520,7 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type { var countStartColumn = columns.Count - 1; - list.Add(new Tuple(item, GetItemCounts(row, countStartColumn, typesToCount))); + list.Add((item, GetItemCounts(row, countStartColumn, typesToCount))); } } @@ -6191,6 +6187,5 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type return item; } - } } diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index 6218d3a086..e55f885504 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -1331,7 +1331,7 @@ namespace Emby.Server.Implementations.Library return ItemRepository.GetItemIdsList(query); } - public QueryResult> GetStudios(InternalItemsQuery query) + public QueryResult<(BaseItem, ItemCounts)> GetStudios(InternalItemsQuery query) { if (query.User != null) { @@ -1342,7 +1342,7 @@ namespace Emby.Server.Implementations.Library return ItemRepository.GetStudios(query); } - public QueryResult> GetGenres(InternalItemsQuery query) + public QueryResult<(BaseItem, ItemCounts)> GetGenres(InternalItemsQuery query) { if (query.User != null) { @@ -1353,7 +1353,7 @@ namespace Emby.Server.Implementations.Library return ItemRepository.GetGenres(query); } - public QueryResult> GetMusicGenres(InternalItemsQuery query) + public QueryResult<(BaseItem, ItemCounts)> GetMusicGenres(InternalItemsQuery query) { if (query.User != null) { @@ -1364,7 +1364,7 @@ namespace Emby.Server.Implementations.Library return ItemRepository.GetMusicGenres(query); } - public QueryResult> GetAllArtists(InternalItemsQuery query) + public QueryResult<(BaseItem, ItemCounts)> GetAllArtists(InternalItemsQuery query) { if (query.User != null) { @@ -1375,7 +1375,7 @@ namespace Emby.Server.Implementations.Library return ItemRepository.GetAllArtists(query); } - public QueryResult> GetArtists(InternalItemsQuery query) + public QueryResult<(BaseItem, ItemCounts)> GetArtists(InternalItemsQuery query) { if (query.User != null) { @@ -1419,7 +1419,7 @@ namespace Emby.Server.Implementations.Library } } - public QueryResult> GetAlbumArtists(InternalItemsQuery query) + public QueryResult<(BaseItem, ItemCounts)> GetAlbumArtists(InternalItemsQuery query) { if (query.User != null) { diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index b1515df439..885709b0c2 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -3,7 +3,7 @@ jellyfin Exe - netcoreapp2.1 + netcoreapp3.0 false diff --git a/MediaBrowser.Api/UserLibrary/ArtistsService.cs b/MediaBrowser.Api/UserLibrary/ArtistsService.cs index 651da1939d..7a8455ff26 100644 --- a/MediaBrowser.Api/UserLibrary/ArtistsService.cs +++ b/MediaBrowser.Api/UserLibrary/ArtistsService.cs @@ -112,7 +112,7 @@ namespace MediaBrowser.Api.UserLibrary return ToOptimizedResult(result); } - protected override QueryResult> GetItems(GetItemsByName request, InternalItemsQuery query) + protected override QueryResult<(BaseItem, ItemCounts)> GetItems(GetItemsByName request, InternalItemsQuery query) { if (request is GetAlbumArtists) { diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs index 471b411279..e3c9ae58e7 100644 --- a/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs +++ b/MediaBrowser.Api/UserLibrary/BaseItemsByNameService.cs @@ -209,9 +209,9 @@ namespace MediaBrowser.Api.UserLibrary }; } - protected virtual QueryResult> GetItems(GetItemsByName request, InternalItemsQuery query) + protected virtual QueryResult<(BaseItem, ItemCounts)> GetItems(GetItemsByName request, InternalItemsQuery query) { - return new QueryResult>(); + return new QueryResult<(BaseItem, ItemCounts)>(); } private void SetItemCounts(BaseItemDto dto, ItemCounts counts) diff --git a/MediaBrowser.Api/UserLibrary/GenresService.cs b/MediaBrowser.Api/UserLibrary/GenresService.cs index baf570d50f..0c04d02dd8 100644 --- a/MediaBrowser.Api/UserLibrary/GenresService.cs +++ b/MediaBrowser.Api/UserLibrary/GenresService.cs @@ -92,7 +92,7 @@ namespace MediaBrowser.Api.UserLibrary return ToOptimizedResult(result); } - protected override QueryResult> GetItems(GetItemsByName request, InternalItemsQuery query) + protected override QueryResult<(BaseItem, ItemCounts)> GetItems(GetItemsByName request, InternalItemsQuery query) { var viewType = GetParentItemViewType(request); diff --git a/MediaBrowser.Api/UserLibrary/MusicGenresService.cs b/MediaBrowser.Api/UserLibrary/MusicGenresService.cs index 4fcc3aa53f..94f5262b08 100644 --- a/MediaBrowser.Api/UserLibrary/MusicGenresService.cs +++ b/MediaBrowser.Api/UserLibrary/MusicGenresService.cs @@ -83,7 +83,7 @@ namespace MediaBrowser.Api.UserLibrary return ToOptimizedResult(result); } - protected override QueryResult> GetItems(GetItemsByName request, InternalItemsQuery query) + protected override QueryResult<(BaseItem, ItemCounts)> GetItems(GetItemsByName request, InternalItemsQuery query) { return LibraryManager.GetMusicGenres(query); } diff --git a/MediaBrowser.Api/UserLibrary/PersonsService.cs b/MediaBrowser.Api/UserLibrary/PersonsService.cs index d317f9f387..c264577788 100644 --- a/MediaBrowser.Api/UserLibrary/PersonsService.cs +++ b/MediaBrowser.Api/UserLibrary/PersonsService.cs @@ -101,7 +101,7 @@ namespace MediaBrowser.Api.UserLibrary throw new NotImplementedException(); } - protected override QueryResult> GetItems(GetItemsByName request, InternalItemsQuery query) + protected override QueryResult<(BaseItem, ItemCounts)> GetItems(GetItemsByName request, InternalItemsQuery query) { var items = LibraryManager.GetPeopleItems(new InternalPeopleQuery { @@ -109,10 +109,10 @@ namespace MediaBrowser.Api.UserLibrary NameContains = query.NameContains ?? query.SearchTerm }); - return new QueryResult> + return new QueryResult<(BaseItem, ItemCounts)> { TotalRecordCount = items.Count, - Items = items.Take(query.Limit ?? int.MaxValue).Select(i => new Tuple(i, new ItemCounts())).ToArray() + Items = items.Take(query.Limit ?? int.MaxValue).Select(i => (i as BaseItem, new ItemCounts())).ToArray() }; } diff --git a/MediaBrowser.Api/UserLibrary/StudiosService.cs b/MediaBrowser.Api/UserLibrary/StudiosService.cs index 4e2483a564..890acc9311 100644 --- a/MediaBrowser.Api/UserLibrary/StudiosService.cs +++ b/MediaBrowser.Api/UserLibrary/StudiosService.cs @@ -91,7 +91,7 @@ namespace MediaBrowser.Api.UserLibrary return ToOptimizedResult(result); } - protected override QueryResult> GetItems(GetItemsByName request, InternalItemsQuery query) + protected override QueryResult<(BaseItem, ItemCounts)> GetItems(GetItemsByName request, InternalItemsQuery query) { return LibraryManager.GetStudios(query); } diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index 60c183d041..ab1f5a6b5e 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -520,12 +520,12 @@ namespace MediaBrowser.Controller.Library void UpdateMediaPath(string virtualFolderName, MediaPathInfo path); void RemoveMediaPath(string virtualFolderName, string path); - QueryResult> GetGenres(InternalItemsQuery query); - QueryResult> GetMusicGenres(InternalItemsQuery query); - QueryResult> GetStudios(InternalItemsQuery query); - QueryResult> GetArtists(InternalItemsQuery query); - QueryResult> GetAlbumArtists(InternalItemsQuery query); - QueryResult> GetAllArtists(InternalItemsQuery query); + QueryResult<(BaseItem, ItemCounts)> GetGenres(InternalItemsQuery query); + QueryResult<(BaseItem, ItemCounts)> GetMusicGenres(InternalItemsQuery query); + QueryResult<(BaseItem, ItemCounts)> GetStudios(InternalItemsQuery query); + QueryResult<(BaseItem, ItemCounts)> GetArtists(InternalItemsQuery query); + QueryResult<(BaseItem, ItemCounts)> GetAlbumArtists(InternalItemsQuery query); + QueryResult<(BaseItem, ItemCounts)> GetAllArtists(InternalItemsQuery query); int GetCount(InternalItemsQuery query); diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs index 5156fce11e..3cb0b76395 100644 --- a/MediaBrowser.Controller/Persistence/IItemRepository.cs +++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs @@ -141,12 +141,12 @@ namespace MediaBrowser.Controller.Persistence int GetCount(InternalItemsQuery query); - QueryResult> GetGenres(InternalItemsQuery query); - QueryResult> GetMusicGenres(InternalItemsQuery query); - QueryResult> GetStudios(InternalItemsQuery query); - QueryResult> GetArtists(InternalItemsQuery query); - QueryResult> GetAlbumArtists(InternalItemsQuery query); - QueryResult> GetAllArtists(InternalItemsQuery query); + QueryResult<(BaseItem, ItemCounts)> GetGenres(InternalItemsQuery query); + QueryResult<(BaseItem, ItemCounts)> GetMusicGenres(InternalItemsQuery query); + QueryResult<(BaseItem, ItemCounts)> GetStudios(InternalItemsQuery query); + QueryResult<(BaseItem, ItemCounts)> GetArtists(InternalItemsQuery query); + QueryResult<(BaseItem, ItemCounts)> GetAlbumArtists(InternalItemsQuery query); + QueryResult<(BaseItem, ItemCounts)> GetAllArtists(InternalItemsQuery query); List GetMusicGenreNames(); List GetStudioNames(); From 3e6819c718a45b44eb3f84439d118ad849ccffa8 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 9 Feb 2019 00:57:58 +0100 Subject: [PATCH 037/104] Don't clone lists --- .../Data/SqliteItemRepository.cs | 4 ++-- .../Library/LibraryManager.cs | 12 +++++------- MediaBrowser.Controller/Library/ILibraryManager.cs | 2 +- .../Persistence/IItemRepository.cs | 2 +- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 6a346f31f6..c7bcb6fa3e 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -536,7 +536,7 @@ namespace Emby.Server.Implementations.Data throw new ArgumentNullException(nameof(item)); } - SaveItems(new List { item }, cancellationToken); + SaveItems(new [] { item }, cancellationToken); } public void SaveImages(BaseItem item) @@ -576,7 +576,7 @@ namespace Emby.Server.Implementations.Data /// or /// cancellationToken /// - public void SaveItems(List items, CancellationToken cancellationToken) + public void SaveItems(IEnumerable items, CancellationToken cancellationToken) { if (items == null) { diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index e55f885504..378693a43f 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -1806,18 +1806,16 @@ namespace Emby.Server.Implementations.Library /// Task. public void CreateItems(IEnumerable items, BaseItem parent, CancellationToken cancellationToken) { - var list = items.ToList(); + ItemRepository.SaveItems(items, cancellationToken); - ItemRepository.SaveItems(list, cancellationToken); - - foreach (var item in list) + foreach (var item in items) { RegisterItem(item); } if (ItemAdded != null) { - foreach (var item in list) + foreach (var item in items) { // With the live tv guide this just creates too much noise if (item.SourceType != SourceType.Library) @@ -1851,7 +1849,7 @@ namespace Emby.Server.Implementations.Library /// /// Updates the item. /// - public void UpdateItems(List items, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken) + public void UpdateItems(IEnumerable items, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken) { foreach (var item in items) { @@ -1906,7 +1904,7 @@ namespace Emby.Server.Implementations.Library /// Task. public void UpdateItem(BaseItem item, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken) { - UpdateItems(new List { item }, parent, updateReason, cancellationToken); + UpdateItems(new [] { item }, parent, updateReason, cancellationToken); } /// diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs index ab1f5a6b5e..511356aa4e 100644 --- a/MediaBrowser.Controller/Library/ILibraryManager.cs +++ b/MediaBrowser.Controller/Library/ILibraryManager.cs @@ -193,7 +193,7 @@ namespace MediaBrowser.Controller.Library /// /// Updates the item. /// - void UpdateItems(List items, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken); + void UpdateItems(IEnumerable items, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken); void UpdateItem(BaseItem item, BaseItem parent, ItemUpdateType updateReason, CancellationToken cancellationToken); /// diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs index 3cb0b76395..47e0f34532 100644 --- a/MediaBrowser.Controller/Persistence/IItemRepository.cs +++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs @@ -32,7 +32,7 @@ namespace MediaBrowser.Controller.Persistence /// /// The items. /// The cancellation token. - void SaveItems(List items, CancellationToken cancellationToken); + void SaveItems(IEnumerable items, CancellationToken cancellationToken); void SaveImages(BaseItem item); From 7722cb3ffab5b8330b34fb27608ba9ff35f6ce81 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 9 Feb 2019 01:09:22 +0100 Subject: [PATCH 038/104] Some Lists -> IEnumerable --- .../Data/SqliteItemRepository.cs | 12 ++++++------ MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs | 8 +++----- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index c7bcb6fa3e..49a510a22c 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -587,7 +587,7 @@ namespace Emby.Server.Implementations.Data CheckDisposed(); - var tuples = new List, BaseItem, string, List>>(); + var tuples = new List<(BaseItem, List, BaseItem, string, List)>(); foreach (var item in items) { var ancestorIds = item.SupportsAncestors ? @@ -599,7 +599,7 @@ namespace Emby.Server.Implementations.Data var userdataKey = item.GetUserDataKeys().FirstOrDefault(); var inheritedTags = item.GetInheritedTags(); - tuples.Add(new Tuple, BaseItem, string, List>(item, ancestorIds, topParent, userdataKey, inheritedTags)); + tuples.Add((item, ancestorIds, topParent, userdataKey, inheritedTags)); } using (WriteLock.Write()) @@ -615,7 +615,7 @@ namespace Emby.Server.Implementations.Data } } - private void SaveItemsInTranscation(IDatabaseConnection db, List, BaseItem, string, List>> tuples) + private void SaveItemsInTranscation(IDatabaseConnection db, IEnumerable<(BaseItem, List, BaseItem, string, List)> tuples) { var statements = PrepareAllSafe(db, new string[] { @@ -2094,9 +2094,9 @@ namespace Emby.Server.Implementations.Data || query.IsLiked.HasValue; } - private readonly List allFields = Enum.GetNames(typeof(ItemFields)) + private readonly ItemFields[] _allFields = Enum.GetNames(typeof(ItemFields)) .Select(i => (ItemFields)Enum.Parse(typeof(ItemFields), i, true)) - .ToList(); + .ToArray(); private string[] GetColumnNamesFromField(ItemFields field) { @@ -2305,7 +2305,7 @@ namespace Emby.Server.Implementations.Data { var list = startColumns.ToList(); - foreach (var field in allFields) + foreach (var field in _allFields) { if (!HasField(query, field)) { diff --git a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs index 7af50c329a..a26f59573c 100644 --- a/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs +++ b/MediaBrowser.Api/UserLibrary/BaseItemsRequest.cs @@ -396,14 +396,12 @@ namespace MediaBrowser.Api.UserLibrary public VideoType[] GetVideoTypes() { - var val = VideoTypes; - - if (string.IsNullOrEmpty(val)) + if (string.IsNullOrEmpty(VideoTypes)) { - return new VideoType[] { }; + return Array.Empty(); } - return val.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(v => (VideoType)Enum.Parse(typeof(VideoType), v, true)).ToArray(); + return VideoTypes.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(v => (VideoType)Enum.Parse(typeof(VideoType), v, true)).ToArray(); } /// From 9dba930a85bc606840918639f4cd0b80c1e1eb2b Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 9 Feb 2019 01:25:14 +0100 Subject: [PATCH 039/104] Warn faster for slow requests --- Emby.Server.Implementations/Data/SqliteItemRepository.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 49a510a22c..7e106569b0 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -2710,13 +2710,11 @@ namespace Emby.Server.Implementations.Data private void AddItem(List items, BaseItem newItem) { - var providerIds = newItem.ProviderIds.ToList(); - for (var i = 0; i < items.Count; i++) { var item = items[i]; - foreach (var providerId in providerIds) + foreach (var providerId in newItem.ProviderIds) { if (providerId.Key == MetadataProviders.TmdbCollection.ToString()) { @@ -2741,10 +2739,10 @@ namespace Emby.Server.Implementations.Data { var elapsed = (DateTime.UtcNow - startDate).TotalMilliseconds; - int slowThreshold = 1000; + int slowThreshold = 100; #if DEBUG - slowThreshold = 250; + slowThreshold = 10; #endif if (elapsed >= slowThreshold) From da9418c1b2348a68bd7a554462c8f355eacb6131 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 9 Feb 2019 01:39:59 +0100 Subject: [PATCH 040/104] Useless copy --- .../Data/SqliteItemRepository.cs | 47 +++++++++++-------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 7e106569b0..6502e4aeda 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -966,7 +966,7 @@ namespace Emby.Server.Implementations.Data if (item.ExtraIds.Length > 0) { - saveItemStatement.TryBind("@ExtraIds", string.Join("|", item.ExtraIds.ToArray())); + saveItemStatement.TryBind("@ExtraIds", string.Join("|", item.ExtraIds)); } else { @@ -2792,7 +2792,7 @@ namespace Emby.Server.Implementations.Data var whereText = whereClauses.Count == 0 ? string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + " where " + string.Join(" AND ", whereClauses); commandText += whereText + GetGroupBy(query) @@ -2916,25 +2916,31 @@ namespace Emby.Server.Implementations.Data private string GetOrderByText(InternalItemsQuery query) { - var orderBy = query.OrderBy.ToList(); - var enableOrderInversion = false; - - if (query.SimilarTo != null && orderBy.Count == 0) + if (string.IsNullOrEmpty(query.SearchTerm)) { - orderBy.Add(new ValueTuple("SimilarityScore", SortOrder.Descending)); - orderBy.Add(new ValueTuple(ItemSortBy.Random, SortOrder.Ascending)); + int oldLen = query.OrderBy.Length; + + if (query.SimilarTo != null && oldLen == 0) + { + var arr = new (string, SortOrder)[oldLen + 2]; + query.OrderBy.CopyTo(arr, 0); + arr[oldLen] = ("SimilarityScore", SortOrder.Descending); + arr[oldLen + 1] = (ItemSortBy.Random, SortOrder.Ascending); + query.OrderBy = arr; + } + } + else + { + query.OrderBy = new [] + { + ("SearchScore", SortOrder.Descending), + (ItemSortBy.SortName, SortOrder.Ascending) + }; } - if (!string.IsNullOrEmpty(query.SearchTerm)) - { - orderBy = new List<(string, SortOrder)>(); - orderBy.Add(new ValueTuple("SearchScore", SortOrder.Descending)); - orderBy.Add(new ValueTuple(ItemSortBy.SortName, SortOrder.Ascending)); - } + var orderBy = query.OrderBy; - query.OrderBy = orderBy.ToArray(); - - if (orderBy.Count == 0) + if (orderBy.Length == 0) { return string.Empty; } @@ -2943,6 +2949,7 @@ namespace Emby.Server.Implementations.Data { var columnMap = MapOrderByField(i.Item1, query); var columnAscending = i.Item2 == SortOrder.Ascending; + const bool enableOrderInversion = false; if (columnMap.Item2 && enableOrderInversion) { columnAscending = !columnAscending; @@ -2954,7 +2961,7 @@ namespace Emby.Server.Implementations.Data })); } - private ValueTuple MapOrderByField(string name, InternalItemsQuery query) + private (string, bool) MapOrderByField(string name, InternalItemsQuery query) { if (string.Equals(name, ItemSortBy.AirTime, StringComparison.OrdinalIgnoreCase)) { @@ -3204,7 +3211,7 @@ namespace Emby.Server.Implementations.Data var whereText = whereClauses.Count == 0 ? string.Empty : - " where " + string.Join(" AND ", whereClauses.ToArray()); + " where " + string.Join(" AND ", whereClauses); commandText += whereText + GetGroupBy(query) @@ -4364,7 +4371,7 @@ namespace Emby.Server.Implementations.Data } else if (query.Years.Length > 1) { - var val = string.Join(",", query.Years.ToArray()); + var val = string.Join(",", query.Years); whereClauses.Add("ProductionYear in (" + val + ")"); } From 8d98885cdae15cc9865e0984e4270ee4a8d9d2db Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 9 Feb 2019 11:53:07 +0100 Subject: [PATCH 041/104] Less string allocations --- .../HttpServer/HttpResultFactory.cs | 33 +++++++++---------- .../HttpServer/StreamWriter.cs | 8 ++--- .../LiveTv/LiveTvManager.cs | 2 +- .../Serialization/JsonSerializer.cs | 21 ++++++++++++ Jellyfin.Server/Jellyfin.Server.csproj | 2 +- .../SocketSharp/WebSocketSharpRequest.cs | 30 +++++++++++++---- MediaBrowser.Api/UserLibrary/ItemsService.cs | 8 ++--- .../Serialization/IJsonSerializer.cs | 8 +++++ 8 files changed, 76 insertions(+), 36 deletions(-) diff --git a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs index 7445fd3c28..e7e3308dc7 100644 --- a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -90,7 +90,7 @@ namespace Emby.Server.Implementations.HttpServer /// private IHasHeaders GetHttpResult(IRequest requestContext, Stream content, string contentType, bool addCachePrevention, IDictionary responseHeaders = null) { - var result = new StreamWriter(content, contentType, _logger); + var result = new StreamWriter(content, contentType); if (responseHeaders == null) { @@ -131,7 +131,7 @@ namespace Emby.Server.Implementations.HttpServer content = Array.Empty(); } - result = new StreamWriter(content, contentType, contentLength, _logger); + result = new StreamWriter(content, contentType, contentLength); } else { @@ -143,7 +143,7 @@ namespace Emby.Server.Implementations.HttpServer responseHeaders = new Dictionary(); } - if (addCachePrevention && !responseHeaders.TryGetValue("Expires", out string expires)) + if (addCachePrevention && !responseHeaders.TryGetValue("Expires", out string _)) { responseHeaders["Expires"] = "-1"; } @@ -175,7 +175,7 @@ namespace Emby.Server.Implementations.HttpServer bytes = Array.Empty(); } - result = new StreamWriter(bytes, contentType, contentLength, _logger); + result = new StreamWriter(bytes, contentType, contentLength); } else { @@ -187,7 +187,7 @@ namespace Emby.Server.Implementations.HttpServer responseHeaders = new Dictionary(); } - if (addCachePrevention && !responseHeaders.TryGetValue("Expires", out string expires)) + if (addCachePrevention && !responseHeaders.TryGetValue("Expires", out string _)) { responseHeaders["Expires"] = "-1"; } @@ -277,9 +277,9 @@ namespace Emby.Server.Implementations.HttpServer private object ToOptimizedResultInternal(IRequest request, T dto, IDictionary responseHeaders = null) { - var contentType = request.ResponseContentType; + var contentType = request.ResponseContentType?.Split(';')[0]; - switch (GetRealContentType(contentType)) + switch (contentType) { case "application/xml": case "text/xml": @@ -333,13 +333,13 @@ namespace Emby.Server.Implementations.HttpServer if (isHeadRequest) { - var result = new StreamWriter(Array.Empty(), contentType, contentLength, _logger); + var result = new StreamWriter(Array.Empty(), contentType, contentLength); AddResponseHeaders(result, responseHeaders); return result; } else { - var result = new StreamWriter(content, contentType, contentLength, _logger); + var result = new StreamWriter(content, contentType, contentLength); AddResponseHeaders(result, responseHeaders); return result; } @@ -348,13 +348,19 @@ namespace Emby.Server.Implementations.HttpServer private byte[] Compress(byte[] bytes, string compressionType) { if (string.Equals(compressionType, "br", StringComparison.OrdinalIgnoreCase)) + { return CompressBrotli(bytes); + } if (string.Equals(compressionType, "deflate", StringComparison.OrdinalIgnoreCase)) + { return Deflate(bytes); + } if (string.Equals(compressionType, "gzip", StringComparison.OrdinalIgnoreCase)) + { return GZip(bytes); + } throw new NotSupportedException(compressionType); } @@ -390,13 +396,6 @@ namespace Emby.Server.Implementations.HttpServer } } - public static string GetRealContentType(string contentType) - { - return contentType == null - ? null - : contentType.Split(';')[0].ToLowerInvariant().Trim(); - } - private static string SerializeToXmlString(object from) { using (var ms = new MemoryStream()) @@ -621,7 +620,7 @@ namespace Emby.Server.Implementations.HttpServer } } - var hasHeaders = new StreamWriter(stream, contentType, _logger) + var hasHeaders = new StreamWriter(stream, contentType) { OnComplete = options.OnComplete, OnError = options.OnError diff --git a/Emby.Server.Implementations/HttpServer/StreamWriter.cs b/Emby.Server.Implementations/HttpServer/StreamWriter.cs index 3269d44cf6..cb2e3580b2 100644 --- a/Emby.Server.Implementations/HttpServer/StreamWriter.cs +++ b/Emby.Server.Implementations/HttpServer/StreamWriter.cs @@ -14,8 +14,6 @@ namespace Emby.Server.Implementations.HttpServer /// public class StreamWriter : IAsyncStreamWriter, IHasHeaders { - private ILogger Logger { get; set; } - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); /// @@ -45,7 +43,7 @@ namespace Emby.Server.Implementations.HttpServer /// The source. /// Type of the content. /// The logger. - public StreamWriter(Stream source, string contentType, ILogger logger) + public StreamWriter(Stream source, string contentType) { if (string.IsNullOrEmpty(contentType)) { @@ -53,7 +51,6 @@ namespace Emby.Server.Implementations.HttpServer } SourceStream = source; - Logger = logger; Headers["Content-Type"] = contentType; @@ -69,7 +66,7 @@ namespace Emby.Server.Implementations.HttpServer /// The source. /// Type of the content. /// The logger. - public StreamWriter(byte[] source, string contentType, int contentLength, ILogger logger) + public StreamWriter(byte[] source, string contentType, int contentLength) { if (string.IsNullOrEmpty(contentType)) { @@ -77,7 +74,6 @@ namespace Emby.Server.Implementations.HttpServer } SourceBytes = source; - Logger = logger; Headers["Content-Type"] = contentType; diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index a363028760..f7ef16fb09 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -184,7 +184,7 @@ namespace Emby.Server.Implementations.LiveTv public QueryResult GetInternalChannels(LiveTvChannelQuery query, DtoOptions dtoOptions, CancellationToken cancellationToken) { - var user = query.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(query.UserId); + var user = query.UserId == Guid.Empty ? null : _userManager.GetUserById(query.UserId); var topFolder = GetInternalLiveTvFolder(cancellationToken); diff --git a/Emby.Server.Implementations/Serialization/JsonSerializer.cs b/Emby.Server.Implementations/Serialization/JsonSerializer.cs index 44898d4986..8ae7fd90cc 100644 --- a/Emby.Server.Implementations/Serialization/JsonSerializer.cs +++ b/Emby.Server.Implementations/Serialization/JsonSerializer.cs @@ -41,6 +41,27 @@ namespace Emby.Server.Implementations.Serialization ServiceStack.Text.JsonSerializer.SerializeToStream(obj, obj.GetType(), stream); } + /// + /// Serializes to stream. + /// + /// The obj. + /// The stream. + /// obj + public void SerializeToStream(T obj, Stream stream) + { + if (obj == null) + { + throw new ArgumentNullException(nameof(obj)); + } + + if (stream == null) + { + throw new ArgumentNullException(nameof(stream)); + } + + ServiceStack.Text.JsonSerializer.SerializeToStream(obj, stream); + } + /// /// Serializes to file. /// diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 885709b0c2..c7e1461bde 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -3,7 +3,7 @@ jellyfin Exe - netcoreapp3.0 + netcoreapp2.2;netcoreapp3.0 false diff --git a/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs b/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs index ebeb18ea06..12ae8169d7 100644 --- a/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs +++ b/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs @@ -99,7 +99,7 @@ namespace Jellyfin.Server.SocketSharp name = name.Trim(HttpTrimCharacters); // First, check for correctly formed multi-line value - // Second, check for absenece of CTL characters + // Second, check for absence of CTL characters int crlf = 0; for (int i = 0; i < name.Length; ++i) { @@ -216,8 +216,13 @@ namespace Jellyfin.Server.SocketSharp { foreach (var acceptsType in acceptContentTypes) { - var contentType = HttpResultFactory.GetRealContentType(acceptsType); - acceptsAnything = acceptsAnything || contentType == "*/*"; + var contentType = acceptsType?.Split(';')[0]; + acceptsAnything = contentType.IndexOf("*/*", StringComparison.Ordinal) != -1; + + if (acceptsAnything) + { + break; + } } if (acceptsAnything) @@ -226,7 +231,7 @@ namespace Jellyfin.Server.SocketSharp { return defaultContentType; } - else if (serverDefaultContentType != null) + else { return serverDefaultContentType; } @@ -269,11 +274,11 @@ namespace Jellyfin.Server.SocketSharp private static string GetQueryStringContentType(IRequest httpReq) { - var format = httpReq.QueryString["format"]; + ReadOnlySpan format = httpReq.QueryString["format"]; if (format == null) { const int formatMaxLength = 4; - var pi = httpReq.PathInfo; + ReadOnlySpan pi = httpReq.PathInfo; if (pi == null || pi.Length <= formatMaxLength) { return null; @@ -281,7 +286,7 @@ namespace Jellyfin.Server.SocketSharp if (pi[0] == '/') { - pi = pi.Substring(1); + pi = pi.Slice(1); } format = LeftPart(pi, '/'); @@ -315,6 +320,17 @@ namespace Jellyfin.Server.SocketSharp return pos == -1 ? strVal : strVal.Substring(0, pos); } + public static ReadOnlySpan LeftPart(ReadOnlySpan strVal, char needle) + { + if (strVal == null) + { + return null; + } + + var pos = strVal.IndexOf(needle); + return pos == -1 ? strVal : strVal.Slice(0, pos); + } + public static string HandlerFactoryPath; private string pathInfo; diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index 46d7c250e8..96b0aa003e 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -90,7 +90,7 @@ namespace MediaBrowser.Api.UserLibrary var options = GetDtoOptions(_authContext, request); - var ancestorIds = new List(); + var ancestorIds = Array.Empty(); var excludeFolderIds = user.Configuration.LatestItemsExcludes; if (parentIdGuid.Equals(Guid.Empty) && excludeFolderIds.Length > 0) @@ -99,12 +99,12 @@ namespace MediaBrowser.Api.UserLibrary .Where(i => i is Folder) .Where(i => !excludeFolderIds.Contains(i.Id.ToString("N"))) .Select(i => i.Id) - .ToList(); + .ToArray(); } var itemsResult = _libraryManager.GetItemsResult(new InternalItemsQuery(user) { - OrderBy = new[] { ItemSortBy.DatePlayed }.Select(i => new ValueTuple(i, SortOrder.Descending)).ToArray(), + OrderBy = new[] { (ItemSortBy.DatePlayed, SortOrder.Descending) }, IsResumable = true, StartIndex = request.StartIndex, Limit = request.Limit, @@ -115,7 +115,7 @@ namespace MediaBrowser.Api.UserLibrary IsVirtualItem = false, CollapseBoxSetItems = false, EnableTotalRecordCount = request.EnableTotalRecordCount, - AncestorIds = ancestorIds.ToArray(), + AncestorIds = ancestorIds, IncludeItemTypes = request.GetIncludeItemTypes(), ExcludeItemTypes = request.GetExcludeItemTypes(), SearchTerm = request.SearchTerm diff --git a/MediaBrowser.Model/Serialization/IJsonSerializer.cs b/MediaBrowser.Model/Serialization/IJsonSerializer.cs index ae0cf6f365..18f51f6525 100644 --- a/MediaBrowser.Model/Serialization/IJsonSerializer.cs +++ b/MediaBrowser.Model/Serialization/IJsonSerializer.cs @@ -14,6 +14,14 @@ namespace MediaBrowser.Model.Serialization /// obj void SerializeToStream(object obj, Stream stream); + /// + /// Serializes to stream. + /// + /// The obj. + /// The stream. + /// obj + void SerializeToStream(T obj, Stream stream); + /// /// Serializes to file. /// From 585b5201f1b3b34427b1b8f8e03258feff651516 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 9 Feb 2019 12:01:11 +0100 Subject: [PATCH 042/104] Last bits --- .../SocketSharp/WebSocketSharpRequest.cs | 37 +++++-------------- 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs b/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs index 12ae8169d7..d862931542 100644 --- a/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs +++ b/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs @@ -27,30 +27,6 @@ namespace Jellyfin.Server.SocketSharp //HandlerFactoryPath = GetHandlerPathIfAny(UrlPrefixes[0]); } - private static string GetHandlerPathIfAny(string listenerUrl) - { - if (listenerUrl == null) - { - return null; - } - - var pos = listenerUrl.IndexOf("://", StringComparison.OrdinalIgnoreCase); - if (pos == -1) - { - return null; - } - - var startHostUrl = listenerUrl.Substring(pos + "://".Length); - var endPos = startHostUrl.IndexOf('/'); - if (endPos == -1) - { - return null; - } - - var endHostUrl = startHostUrl.Substring(endPos + 1); - return string.IsNullOrEmpty(endHostUrl) ? null : endHostUrl.TrimEnd('/'); - } - public HttpListenerRequest HttpRequest => request; public object OriginalRequest => request; @@ -216,6 +192,8 @@ namespace Jellyfin.Server.SocketSharp { foreach (var acceptsType in acceptContentTypes) { + // TODO: @bond move to Span when Span.Split lands + // https://github.com/dotnet/corefx/issues/26528 var contentType = acceptsType?.Split(';')[0]; acceptsAnything = contentType.IndexOf("*/*", StringComparison.Ordinal) != -1; @@ -342,7 +320,7 @@ namespace Jellyfin.Server.SocketSharp { var mode = HandlerFactoryPath; - var pos = request.RawUrl.IndexOf("?", StringComparison.Ordinal); + var pos = request.RawUrl.IndexOf('?', StringComparison.Ordinal); if (pos != -1) { var path = request.RawUrl.Substring(0, pos); @@ -524,10 +502,13 @@ namespace Jellyfin.Server.SocketSharp public static string NormalizePathInfo(string pathInfo, string handlerPath) { - var trimmed = pathInfo.TrimStart('/'); - if (handlerPath != null && trimmed.StartsWith(handlerPath, StringComparison.OrdinalIgnoreCase)) + if (handlerPath != null) { - return trimmed.Substring(handlerPath.Length); + var trimmed = pathInfo.TrimStart('/'); + if (trimmed.StartsWith(handlerPath, StringComparison.OrdinalIgnoreCase)) + { + return trimmed.Substring(handlerPath.Length); + } } return pathInfo; From ea446fd4a3c41c1350a4faf34044bdf808d334fd Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 9 Feb 2019 16:06:37 +0100 Subject: [PATCH 043/104] Revert back to netcoreapp2.1 --- Jellyfin.Server/Jellyfin.Server.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index c7e1461bde..fcfeeb225e 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -3,7 +3,7 @@ jellyfin Exe - netcoreapp2.2;netcoreapp3.0 + netcoreapp2.2 false From 3f13851be54ce97df72fc27a15ee74c7600e38b1 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Tue, 12 Feb 2019 21:06:34 +0100 Subject: [PATCH 044/104] Address comments --- Emby.Server.Implementations/HttpServer/HttpResultFactory.cs | 3 ++- Jellyfin.Server/Jellyfin.Server.csproj | 2 +- Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs index e7e3308dc7..85a08b05ac 100644 --- a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -277,7 +277,8 @@ namespace Emby.Server.Implementations.HttpServer private object ToOptimizedResultInternal(IRequest request, T dto, IDictionary responseHeaders = null) { - var contentType = request.ResponseContentType?.Split(';')[0]; + // TODO: @bond use Span and .Equals + var contentType = request.ResponseContentType?.Split(';')[0].Trim().ToLowerInvariant(); switch (contentType) { diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index fcfeeb225e..b1515df439 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -3,7 +3,7 @@ jellyfin Exe - netcoreapp2.2 + netcoreapp2.1 false diff --git a/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs b/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs index d862931542..c2b71e9ef7 100644 --- a/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs +++ b/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs @@ -194,8 +194,8 @@ namespace Jellyfin.Server.SocketSharp { // TODO: @bond move to Span when Span.Split lands // https://github.com/dotnet/corefx/issues/26528 - var contentType = acceptsType?.Split(';')[0]; - acceptsAnything = contentType.IndexOf("*/*", StringComparison.Ordinal) != -1; + var contentType = acceptsType?.Split(';')[0].Trim(); + acceptsAnything = contentType.Equals("*/*", StringComparison.OrdinalIgnoreCase); if (acceptsAnything) { From c74028d08d4fcbd2a921423f5b2b6dea7012a11e Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Tue, 12 Feb 2019 20:50:47 +0100 Subject: [PATCH 045/104] Address comments --- Emby.Server.Implementations/ApplicationHost.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 41ac4fcffa..784486d524 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -477,7 +477,6 @@ namespace Emby.Server.Implementations catch (Exception ex) { Logger.LogError(ex, "Error creating {Type}", type); - // Don't blow up in release mode return null; } } @@ -767,7 +766,8 @@ namespace Emby.Server.Implementations SessionManager = new SessionManager(UserDataManager, LoggerFactory, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, JsonSerializer, this, HttpClient, AuthenticationRepository, DeviceManager, MediaSourceManager); serviceCollection.AddSingleton(SessionManager); - serviceCollection.AddSingleton(new DlnaManager(XmlSerializer, FileSystemManager, ApplicationPaths, LoggerFactory, JsonSerializer, this, assemblyInfo)); + serviceCollection.AddSingleton( + new DlnaManager(XmlSerializer, FileSystemManager, ApplicationPaths, LoggerFactory, JsonSerializer, this, assemblyInfo)); CollectionManager = new CollectionManager(LibraryManager, ApplicationPaths, LocalizationManager, FileSystemManager, LibraryMonitor, LoggerFactory, ProviderManager); serviceCollection.AddSingleton(CollectionManager); @@ -784,7 +784,8 @@ namespace Emby.Server.Implementations NotificationManager = new NotificationManager(LoggerFactory, UserManager, ServerConfigurationManager); serviceCollection.AddSingleton(NotificationManager); - serviceCollection.AddSingleton(new DeviceDiscovery(LoggerFactory, ServerConfigurationManager, SocketFactory)); + serviceCollection.AddSingleton( + new DeviceDiscovery(LoggerFactory, ServerConfigurationManager, SocketFactory)); ChapterManager = new ChapterManager(LibraryManager, LoggerFactory, ServerConfigurationManager, ItemRepository); serviceCollection.AddSingleton(ChapterManager); @@ -1381,9 +1382,6 @@ namespace Emby.Server.Implementations } } - // Gets all plugin assemblies by first reading all bytes of the .dll and calling Assembly.Load against that - // This will prevent the .dll file from getting locked, and allow us to replace it when needed - // Include composable parts in the Api assembly yield return typeof(ApiEntryPoint).Assembly; From a5882ae162e1bdae7f9094c6bb63cf765ad8123f Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Tue, 12 Feb 2019 22:15:11 +0100 Subject: [PATCH 046/104] Treat warnings as errors for release builds --- Jellyfin.Server/Jellyfin.Server.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index b1515df439..fe1397bcbe 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -20,6 +20,10 @@ + + true + + From 3f878d63a5ffd878cf37c3086a2a4a7b3bd8a891 Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Tue, 12 Feb 2019 22:44:01 +0100 Subject: [PATCH 047/104] Added Debug build and seperate the check-abi pipeline. --- .drone.yml | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/.drone.yml b/.drone.yml index f1212d3f96..972bf36f3a 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,5 +1,37 @@ +--- kind: pipeline -name: build +name: build-debug + +steps: +- name: submodules + image: docker:git + commands: + - git submodule update --init --recursive + +- name: build + image: microsoft/dotnet:2-sdk + commands: + - dotnet publish "Jellyfin.Server" --configuration Debug --output "../ci/ci-debug" + +--- +kind: pipeline +name: build-release + +steps: +- name: submodules + image: docker:git + commands: + - git submodule update --init --recursive + +- name: build + image: microsoft/dotnet:2-sdk + commands: + - dotnet publish "Jellyfin.Server" --configuration Release --output "../ci/ci-release" + +--- + +kind: pipeline +name: check-abi steps: - name: submodules From f2811323c24f63f8363bfd0ff316b061b3a18495 Mon Sep 17 00:00:00 2001 From: WWWesten Date: Sun, 10 Feb 2019 17:32:29 +0000 Subject: [PATCH 048/104] Translated using Weblate (Kazakh) Currently translated at 100.0% (94 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/kk/ --- Emby.Server.Implementations/Localization/Core/kk.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/kk.json b/Emby.Server.Implementations/Localization/Core/kk.json index ae256f79d6..130a6ac05d 100644 --- a/Emby.Server.Implementations/Localization/Core/kk.json +++ b/Emby.Server.Implementations/Localization/Core/kk.json @@ -33,7 +33,7 @@ "LabelIpAddressValue": "IP-мекенжайы: {0}", "LabelRunningTimeValue": "Іске қосылу уақыты: {0}", "Latest": "Ең кейінгі", - "MessageApplicationUpdated": "Jellyfin Server жаңартылды.", + "MessageApplicationUpdated": "Jellyfin Server жаңартылды", "MessageApplicationUpdatedTo": "Jellyfin Server {0} үшін жаңартылды", "MessageNamedServerConfigurationUpdatedWithValue": "Сервер теңшелімі ({0} бөлімі) жаңартылды", "MessageServerConfigurationUpdated": "Сервер теңшелімі жаңартылды", @@ -75,7 +75,7 @@ "Songs": "Әуендер", "StartupEmbyServerIsLoading": "Jellyfin Server жүктелуде. Әрекетті көп ұзамай қайталаңыз.", "SubtitleDownloadFailureForItem": "Субтитрлер {0} үшін жүктеліп алынуы сәтсіз", - "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", + "SubtitleDownloadFailureFromForItem": "{1} үшін субтитрлерді {0} көзінен жүктеп алу сәтсіз", "SubtitlesDownloadedForItem": "{0} үшін субтитрлер жүктеліп алынды", "Sync": "Үндестіру", "System": "Жүйе", From da2554bd539c69c9aa804dcd3ebd7f324159b1c2 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Tue, 12 Feb 2019 06:24:40 +0000 Subject: [PATCH 049/104] Translated using Weblate (Danish) Currently translated at 100.0% (94 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/da/ --- .../Localization/Core/da.json | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/da.json b/Emby.Server.Implementations/Localization/Core/da.json index 51f3a46a6e..9d4d740996 100644 --- a/Emby.Server.Implementations/Localization/Core/da.json +++ b/Emby.Server.Implementations/Localization/Core/da.json @@ -2,10 +2,10 @@ "Albums": "Album", "AppDeviceValues": "App: {0}, Enhed: {1}", "Application": "Applikation", - "Artists": "Kunstner", + "Artists": "Kunstnere", "AuthenticationSucceededWithUserName": "{0} bekræftet med succes", "Books": "Bøger", - "CameraImageUploadedFrom": "Et nye billede fra kamera er blevet uploadet fra {0}", + "CameraImageUploadedFrom": "Et nyt kamerabillede er blevet uploadet fra {0}", "Channels": "Kanaler", "ChapterNameValue": "Kapitel {0}", "Collections": "Samlinger", @@ -14,41 +14,41 @@ "FailedLoginAttemptWithUserName": "Fejlet loginforsøg fra {0}", "Favorites": "Favoritter", "Folders": "Mapper", - "Genres": "Genre", + "Genres": "Genrer", "HeaderAlbumArtists": "Albumkunstnere", "HeaderCameraUploads": "Kamera Uploads", "HeaderContinueWatching": "Fortsæt Afspilning", "HeaderFavoriteAlbums": "Favoritalbum", "HeaderFavoriteArtists": "Favoritkunstnere", - "HeaderFavoriteEpisodes": "Favoritepisoder", - "HeaderFavoriteShows": "Favorit serier", - "HeaderFavoriteSongs": "Favoritsange", + "HeaderFavoriteEpisodes": "Favorit-afsnit", + "HeaderFavoriteShows": "Favorit-serier", + "HeaderFavoriteSongs": "Favorit-sange", "HeaderLiveTV": "Live TV", "HeaderNextUp": "Næste", - "HeaderRecordingGroups": "Optagegrupper", + "HeaderRecordingGroups": "Optagelsesgrupper", "HomeVideos": "Hjemmevideoer", - "Inherit": "Arv", + "Inherit": "Nedarv", "ItemAddedWithName": "{0} blev tilføjet til biblioteket", "ItemRemovedWithName": "{0} blev fjernet fra biblioteket", "LabelIpAddressValue": "IP-adresse: {0}", "LabelRunningTimeValue": "Spilletid: {0}", "Latest": "Seneste", "MessageApplicationUpdated": "Jellyfin Server er blevet opdateret", - "MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "Server konfigurationssektion {0} er blevet opdateret", - "MessageServerConfigurationUpdated": "Serverkonfiguration er blevet opdateret", + "MessageApplicationUpdatedTo": "Jellyfin Server er blevet opdateret til {0}", + "MessageNamedServerConfigurationUpdatedWithValue": "Serverkonfigurationsafsnit {0} er blevet opdateret", + "MessageServerConfigurationUpdated": "Serverkonfigurationen er blevet opdateret", "MixedContent": "Blandet indhold", "Movies": "Film", "Music": "Musik", "MusicVideos": "Musikvideoer", - "NameInstallFailed": "{0} installation failed", + "NameInstallFailed": "{0} installationen mislykkedes", "NameSeasonNumber": "Sæson {0}", - "NameSeasonUnknown": "Season Unknown", - "NewVersionIsAvailable": "A new version of Jellyfin Server is available for download.", + "NameSeasonUnknown": "Ukendt Sæson", + "NewVersionIsAvailable": "En ny version af Jellyfin Server er tilgængelig til download.", "NotificationOptionApplicationUpdateAvailable": "Opdatering til applikation tilgængelig", "NotificationOptionApplicationUpdateInstalled": "Opdatering til applikation installeret", - "NotificationOptionAudioPlayback": "Audioafspilning påbegyndt", - "NotificationOptionAudioPlaybackStopped": "Audioafspilning stoppet", + "NotificationOptionAudioPlayback": "Lydafspilning påbegyndt", + "NotificationOptionAudioPlaybackStopped": "Lydafspilning stoppet", "NotificationOptionCameraImageUploaded": "Kamerabillede uploadet", "NotificationOptionInstallationFailed": "Installationsfejl", "NotificationOptionNewLibraryContent": "Nyt indhold tilføjet", @@ -70,16 +70,16 @@ "ProviderValue": "Udbyder: {0}", "ScheduledTaskFailedWithName": "{0} fejlet", "ScheduledTaskStartedWithName": "{0} påbegyndt", - "ServerNameNeedsToBeRestarted": "{0} needs to be restarted", - "Shows": "Shows", + "ServerNameNeedsToBeRestarted": "{0} skal genstartes", + "Shows": "Serier", "Songs": "Sange", - "StartupEmbyServerIsLoading": "Jellyfin Server indlæser. Prøv venligst igen om kort tid.", + "StartupEmbyServerIsLoading": "Jellyfin Server er i gang med at starte op. Prøv venligst igen om lidt.", "SubtitleDownloadFailureForItem": "Fejlet i download af undertekster for {0}", - "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", + "SubtitleDownloadFailureFromForItem": "Undertekster kunne ikke downloades fra {0} til {1}", "SubtitlesDownloadedForItem": "Undertekster downloadet for {0}", "Sync": "Synk", "System": "System", - "TvShows": "TV Shows", + "TvShows": "TV serier", "User": "Bruger", "UserCreatedWithName": "Bruger {0} er blevet oprettet", "UserDeletedWithName": "Brugeren {0} er blevet slettet", @@ -88,10 +88,10 @@ "UserOfflineFromDevice": "{0} har afbrudt fra {1}", "UserOnlineFromDevice": "{0} er online fra {1}", "UserPasswordChangedWithName": "Adgangskode er ændret for bruger {0}", - "UserPolicyUpdatedWithName": "User policy has been updated for {0}", + "UserPolicyUpdatedWithName": "Brugerpolitik er blevet opdateret for {0}", "UserStartedPlayingItemWithValues": "{0} har påbegyndt afspilning af {1}", - "UserStoppedPlayingItemWithValues": "{0} har afsluttet afspilning af {1}", - "ValueHasBeenAddedToLibrary": "{0} has been added to your media library", + "UserStoppedPlayingItemWithValues": "{0} har afsluttet afspilning af {1} på {2}", + "ValueHasBeenAddedToLibrary": "{0} er blevet tilføjet til dit mediebibliotek", "ValueSpecialEpisodeName": "Special - {0}", "VersionNumber": "Version {0}" } From 18f0d996c0537678ffc4d1b0bc9bf4cde83196ce Mon Sep 17 00:00:00 2001 From: Leo Verto Date: Sun, 10 Feb 2019 02:58:26 +0000 Subject: [PATCH 050/104] Translated using Weblate (German) Currently translated at 100.0% (94 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/de/ --- .../Localization/Core/de.json | 54 +++++++++---------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/de.json b/Emby.Server.Implementations/Localization/Core/de.json index 7bd2e90fe4..6fd63a5140 100644 --- a/Emby.Server.Implementations/Localization/Core/de.json +++ b/Emby.Server.Implementations/Localization/Core/de.json @@ -3,61 +3,61 @@ "AppDeviceValues": "App: {0}, Gerät: {1}", "Application": "Anwendung", "Artists": "Interpreten", - "AuthenticationSucceededWithUserName": "{0} erfolgreich authentifiziert", + "AuthenticationSucceededWithUserName": "{0} hat sich angemeldet", "Books": "Bücher", - "CameraImageUploadedFrom": "Ein neues Bild wurde hochgeladen von {0}", + "CameraImageUploadedFrom": "Ein neues Foto wurde hochgeladen von {0}", "Channels": "Kanäle", "ChapterNameValue": "Kapitel {0}", "Collections": "Sammlungen", "DeviceOfflineWithName": "{0} wurde getrennt", - "DeviceOnlineWithName": "{0} ist verbunden", + "DeviceOnlineWithName": "{0} hat sich verbunden", "FailedLoginAttemptWithUserName": "Fehlgeschlagener Anmeldeversuch von {0}", "Favorites": "Favoriten", "Folders": "Verzeichnisse", "Genres": "Genres", - "HeaderAlbumArtists": "Album-Künstler", - "HeaderCameraUploads": "Kamera Uploads", + "HeaderAlbumArtists": "Album-Interpreten", + "HeaderCameraUploads": "Kamera-Uploads", "HeaderContinueWatching": "Weiterschauen", "HeaderFavoriteAlbums": "Lieblingsalben", - "HeaderFavoriteArtists": "Interpreten Favoriten", + "HeaderFavoriteArtists": "Lieblings-Interpreten", "HeaderFavoriteEpisodes": "Lieblingsepisoden", "HeaderFavoriteShows": "Lieblingsserien", - "HeaderFavoriteSongs": "Lieder Favoriten", - "HeaderLiveTV": "Live TV", + "HeaderFavoriteSongs": "Lieblingslieder", + "HeaderLiveTV": "Live-TV", "HeaderNextUp": "Als Nächstes", "HeaderRecordingGroups": "Aufnahme-Gruppen", "HomeVideos": "Heimvideos", "Inherit": "Übernehmen", "ItemAddedWithName": "{0} wurde der Bibliothek hinzugefügt", "ItemRemovedWithName": "{0} wurde aus der Bibliothek entfernt", - "LabelIpAddressValue": "IP Adresse: {0}", + "LabelIpAddressValue": "IP-Adresse: {0}", "LabelRunningTimeValue": "Laufzeit: {0}", "Latest": "Neueste", - "MessageApplicationUpdated": "Jellyfin Server wurde auf den neusten Stand gebracht.", - "MessageApplicationUpdatedTo": "Jellyfin Server wurde auf Version {0} aktualisiert", + "MessageApplicationUpdated": "Jellyfin-Server wurde aktualisiert", + "MessageApplicationUpdatedTo": "Jellyfin-Server wurde auf Version {0} aktualisiert", "MessageNamedServerConfigurationUpdatedWithValue": "Der Server Einstellungsbereich {0} wurde aktualisiert", - "MessageServerConfigurationUpdated": "Server Einstellungen wurden aktualisiert", + "MessageServerConfigurationUpdated": "Servereinstellungen wurden aktualisiert", "MixedContent": "Gemischte Inhalte", "Movies": "Filme", "Music": "Musik", "MusicVideos": "Musikvideos", - "NameInstallFailed": "{0} Installation fehlgeschlagen", + "NameInstallFailed": "Installation von {0} fehlgeschlagen", "NameSeasonNumber": "Staffel {0}", "NameSeasonUnknown": "Staffel unbekannt", - "NewVersionIsAvailable": "Eine neue Version von Jellyfin Server steht zum Download bereit.", + "NewVersionIsAvailable": "Eine neue Version von Jellyfin-Server steht zum Download bereit.", "NotificationOptionApplicationUpdateAvailable": "Anwendungsaktualisierung verfügbar", "NotificationOptionApplicationUpdateInstalled": "Anwendungsaktualisierung installiert", "NotificationOptionAudioPlayback": "Audiowiedergabe gestartet", "NotificationOptionAudioPlaybackStopped": "Audiowiedergabe gestoppt", - "NotificationOptionCameraImageUploaded": "Kamera Bild hochgeladen", + "NotificationOptionCameraImageUploaded": "Foto hochgeladen", "NotificationOptionInstallationFailed": "Installationsfehler", "NotificationOptionNewLibraryContent": "Neuer Inhalt hinzugefügt", - "NotificationOptionPluginError": "Plugin Fehler", + "NotificationOptionPluginError": "Plugin-Fehler", "NotificationOptionPluginInstalled": "Plugin installiert", "NotificationOptionPluginUninstalled": "Plugin deinstalliert", "NotificationOptionPluginUpdateInstalled": "Pluginaktualisierung installiert", "NotificationOptionServerRestartRequired": "Serverneustart notwendig", - "NotificationOptionTaskFailed": "Geplante Aufgaben fehlgeschlagen", + "NotificationOptionTaskFailed": "Geplante Aufgabe fehlgeschlagen", "NotificationOptionUserLockedOut": "Benutzer ausgeschlossen", "NotificationOptionVideoPlayback": "Videowiedergabe gestartet", "NotificationOptionVideoPlaybackStopped": "Videowiedergabe gestoppt", @@ -68,18 +68,18 @@ "PluginUninstalledWithName": "{0} wurde deinstalliert", "PluginUpdatedWithName": "{0} wurde aktualisiert", "ProviderValue": "Anbieter: {0}", - "ScheduledTaskFailedWithName": "{0} fehlgeschlagen", - "ScheduledTaskStartedWithName": "{0} gestartet", + "ScheduledTaskFailedWithName": "{0} ist fehlgeschlagen", + "ScheduledTaskStartedWithName": "{0} wurde gestartet", "ServerNameNeedsToBeRestarted": "{0} muss neu gestartet werden", "Shows": "Serien", "Songs": "Songs", - "StartupEmbyServerIsLoading": "Jellyfin Server startet, bitte versuche es gleich noch einmal.", + "StartupEmbyServerIsLoading": "Jellyfin-Server startet, bitte versuche es gleich noch einmal.", "SubtitleDownloadFailureForItem": "Download der Untertitel fehlgeschlagen für {0}", - "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", + "SubtitleDownloadFailureFromForItem": "Untertitel von {0} für {1} konnten nicht heruntergeladen werden", "SubtitlesDownloadedForItem": "Untertitel heruntergeladen für {0}", "Sync": "Synchronisation", "System": "System", - "TvShows": "TV Sendungen", + "TvShows": "TV-Sendungen", "User": "Benutzer", "UserCreatedWithName": "Benutzer {0} wurde erstellt", "UserDeletedWithName": "Benutzer {0} wurde gelöscht", @@ -88,10 +88,10 @@ "UserOfflineFromDevice": "{0} wurde getrennt von {1}", "UserOnlineFromDevice": "{0} ist online von {1}", "UserPasswordChangedWithName": "Das Passwort für Benutzer {0} wurde geändert", - "UserPolicyUpdatedWithName": "Benutzerrichtlinie wurde für {0} aktualisiert", - "UserStartedPlayingItemWithValues": "{0} hat die Wiedergabe von {1} gestartet", - "UserStoppedPlayingItemWithValues": "{0} hat die Wiedergabe von {1} beendet", - "ValueHasBeenAddedToLibrary": "{0} wurde ihrer Bibliothek hinzugefügt", - "ValueSpecialEpisodeName": "Special - {0}", + "UserPolicyUpdatedWithName": "Benutzerrichtlinie von {0} wurde aktualisiert", + "UserStartedPlayingItemWithValues": "{0} hat die Wiedergabe von {1} auf {2} gestartet", + "UserStoppedPlayingItemWithValues": "{0} hat die Wiedergabe von {1} auf {2} beendet", + "ValueHasBeenAddedToLibrary": "{0} wurde deiner Bibliothek hinzugefügt", + "ValueSpecialEpisodeName": "Extra - {0}", "VersionNumber": "Version {0}" } From 3a6a5baa8e25c4373c9b9454372922ffbcac4c6f Mon Sep 17 00:00:00 2001 From: ZsiGiT Date: Sun, 10 Feb 2019 14:37:56 +0000 Subject: [PATCH 051/104] Translated using Weblate (Hungarian) Currently translated at 100.0% (94 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/hu/ --- Emby.Server.Implementations/Localization/Core/hu.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/hu.json b/Emby.Server.Implementations/Localization/Core/hu.json index 911fe36db2..c0f988abec 100644 --- a/Emby.Server.Implementations/Localization/Core/hu.json +++ b/Emby.Server.Implementations/Localization/Core/hu.json @@ -17,7 +17,7 @@ "Genres": "Műfajok", "HeaderAlbumArtists": "Album Előadók", "HeaderCameraUploads": "Kamera feltöltések", - "HeaderContinueWatching": "Vetítés(ek) folytatása", + "HeaderContinueWatching": "Folyamatban lévő filmek", "HeaderFavoriteAlbums": "Kedvenc Albumok", "HeaderFavoriteArtists": "Kedvenc Művészek", "HeaderFavoriteEpisodes": "Kedvenc Epizódok", @@ -75,7 +75,7 @@ "Songs": "Dalok", "StartupEmbyServerIsLoading": "A Jellyfin Szerver betöltődik. Kérlek próbáld újra később.", "SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}", - "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", + "SubtitleDownloadFailureFromForItem": "Nem sikerült a felirat letöltése innen: {0} ehhez: {1}", "SubtitlesDownloadedForItem": "Letöltött feliratok a következőhöz {0}", "Sync": "Szinkronizál", "System": "Rendszer", @@ -89,8 +89,8 @@ "UserOnlineFromDevice": "{0} online itt: {1}", "UserPasswordChangedWithName": "Jelszó megváltozott a következő felhasználó számára: {0}", "UserPolicyUpdatedWithName": "A felhasználói házirend frissítve lett {0}", - "UserStartedPlayingItemWithValues": "{0} elkezdte játszani a következőt: {1}", - "UserStoppedPlayingItemWithValues": "{0} befejezte a következőt: {1}", + "UserStartedPlayingItemWithValues": "{0} elkezdte játszani a következőt: {1} itt: {2}", + "UserStoppedPlayingItemWithValues": "{0} befejezte a következőt: {1} itt: {2}", "ValueHasBeenAddedToLibrary": "{0} hozzáadva a médiatárhoz", "ValueSpecialEpisodeName": "Special - {0}", "VersionNumber": "Verzió: {0}" From 4ed90d4658bcada73c1a6ff24447fa71f3825ec3 Mon Sep 17 00:00:00 2001 From: WWWesten Date: Tue, 12 Feb 2019 21:42:12 +0000 Subject: [PATCH 052/104] Translated using Weblate (Kazakh) Currently translated at 100.0% (94 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/kk/ --- .../Localization/Core/kk.json | 188 +++++++++--------- 1 file changed, 94 insertions(+), 94 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/kk.json b/Emby.Server.Implementations/Localization/Core/kk.json index 130a6ac05d..a122f1f09a 100644 --- a/Emby.Server.Implementations/Localization/Core/kk.json +++ b/Emby.Server.Implementations/Localization/Core/kk.json @@ -1,97 +1,97 @@ { - "Albums": "Альбомдар", - "AppDeviceValues": "Қолданба: {0}, Құрылғы: {1}", - "Application": "Қолданба", - "Artists": "Орындаушылар", - "AuthenticationSucceededWithUserName": "{0} түпнұсқалығын расталуы сәтті", - "Books": "Кітаптар", - "CameraImageUploadedFrom": "Жаңа сурет {0} камерасынан жүктеп алынды", - "Channels": "Арналар", - "ChapterNameValue": "{0}-сахна", - "Collections": "Жиынтықтар", - "DeviceOfflineWithName": "{0} ажыратылған", - "DeviceOnlineWithName": "{0} қосылған", - "FailedLoginAttemptWithUserName": "{0} тарапынан кіру әрекеті сәтсіз", - "Favorites": "Таңдаулылар", - "Folders": "Қалталар", - "Genres": "Жанрлар", - "HeaderAlbumArtists": "Альбом орындаушылары", - "HeaderCameraUploads": "Камерадан жүктелгендер", - "HeaderContinueWatching": "Қарауды жалғастыру", - "HeaderFavoriteAlbums": "Таңдаулы альбомдар", - "HeaderFavoriteArtists": "Таңдаулы орындаушылар", - "HeaderFavoriteEpisodes": "Таңдаулы бөлімдер", - "HeaderFavoriteShows": "Таңдаулы көрсетімдер", - "HeaderFavoriteSongs": "Таңдаулы әуендер", - "HeaderLiveTV": "Эфир", - "HeaderNextUp": "Кезекті", - "HeaderRecordingGroups": "Жазба топтары", - "HomeVideos": "Үйлік бейнелер", - "Inherit": "Мұраға иелену", - "ItemAddedWithName": "{0} тасығышханаға үстелінді", - "ItemRemovedWithName": "{0} тасығышханадан аласталды", - "LabelIpAddressValue": "IP-мекенжайы: {0}", - "LabelRunningTimeValue": "Іске қосылу уақыты: {0}", - "Latest": "Ең кейінгі", - "MessageApplicationUpdated": "Jellyfin Server жаңартылды", - "MessageApplicationUpdatedTo": "Jellyfin Server {0} үшін жаңартылды", - "MessageNamedServerConfigurationUpdatedWithValue": "Сервер теңшелімі ({0} бөлімі) жаңартылды", - "MessageServerConfigurationUpdated": "Сервер теңшелімі жаңартылды", - "MixedContent": "Аралас мазмұн", - "Movies": "Фильмдер", - "Music": "Музыка", - "MusicVideos": "Музыкалық бейнелер", - "NameInstallFailed": "{0} орнатылуы сәтсіз", - "NameSeasonNumber": "{0}-маусым", - "NameSeasonUnknown": "Белгісіз маусым", - "NewVersionIsAvailable": "Жаңа Jellyfin Server нұсқасы жүктеп алуға қолжетімді.", - "NotificationOptionApplicationUpdateAvailable": "Қолданба жаңартуы қолжетімді", - "NotificationOptionApplicationUpdateInstalled": "Қолданба жаңартуы орнатылды", - "NotificationOptionAudioPlayback": "Дыбыс ойнатуы басталды", - "NotificationOptionAudioPlaybackStopped": "Дыбыс ойнатуы тоқтатылды", - "NotificationOptionCameraImageUploaded": "Камерадан фотосурет кері қотарылған", - "NotificationOptionInstallationFailed": "Орнату сәтсіздігі", - "NotificationOptionNewLibraryContent": "Жаңа мазмұн үстелген", - "NotificationOptionPluginError": "Плагин сәтсіздігі", - "NotificationOptionPluginInstalled": "Плагин орнатылды", - "NotificationOptionPluginUninstalled": "Плагин орнатуы болдырылмады", - "NotificationOptionPluginUpdateInstalled": "Плагин жаңартуы орнатылды", - "NotificationOptionServerRestartRequired": "Серверді қайта іске қосу қажет", - "NotificationOptionTaskFailed": "Жоспарлаған тапсырма сәтсіздігі", - "NotificationOptionUserLockedOut": "Пайдаланушы құрсаулы", - "NotificationOptionVideoPlayback": "Бейне ойнатуы басталды", - "NotificationOptionVideoPlaybackStopped": "Бейне ойнатуы тоқтатылды", - "Photos": "Фотосуреттер", - "Playlists": "Ойнату тізімдері", - "Plugin": "Плагин", - "PluginInstalledWithName": "{0} орнатылды", - "PluginUninstalledWithName": "{0} жойылды", - "PluginUpdatedWithName": "{0} жаңартылды", - "ProviderValue": "Жеткізуші: {0}", - "ScheduledTaskFailedWithName": "{0} сәтсіз", - "ScheduledTaskStartedWithName": "{0} іске қосылды", - "ServerNameNeedsToBeRestarted": "{0} қайта іске қосу қажет", - "Shows": "Көрсетімдер", - "Songs": "Әуендер", - "StartupEmbyServerIsLoading": "Jellyfin Server жүктелуде. Әрекетті көп ұзамай қайталаңыз.", + "Albums": "Álbomdar", + "AppDeviceValues": "Qoldanba: {0}, Qurylǵy: {1}", + "Application": "Qoldanba", + "Artists": "Oryndaýshylar", + "AuthenticationSucceededWithUserName": "{0} túpnusqalyǵyn rastalýy sátti", + "Books": "Kitaptar", + "CameraImageUploadedFrom": "Jańa sýret {0} kamerasynan júktep alyndy", + "Channels": "Arnalar", + "ChapterNameValue": "{0}-sahna", + "Collections": "Jıyntyqtar", + "DeviceOfflineWithName": "{0} ajyratylǵan", + "DeviceOnlineWithName": "{0} qosylǵan", + "FailedLoginAttemptWithUserName": "{0} tarapynan kirý áreketi sátsiz", + "Favorites": "Tańdaýlylar", + "Folders": "Qaltalar", + "Genres": "Janrlar", + "HeaderAlbumArtists": "Álbom oryndaýshylary", + "HeaderCameraUploads": "Kameradan júktelgender", + "HeaderContinueWatching": "Qaraýdy jalǵastyrý", + "HeaderFavoriteAlbums": "Tańdaýly álbomdar", + "HeaderFavoriteArtists": "Tańdaýly oryndaýshylar", + "HeaderFavoriteEpisodes": "Tańdaýly bólimder", + "HeaderFavoriteShows": "Tańdaýly kórsetimder", + "HeaderFavoriteSongs": "Tańdaýly áýender", + "HeaderLiveTV": "Efır", + "HeaderNextUp": "Kezekti", + "HeaderRecordingGroups": "Jazba toptary", + "HomeVideos": "Úılik beıneler", + "Inherit": "Muraǵa ıelený", + "ItemAddedWithName": "{0} tasyǵyshhanaǵa ústelindi", + "ItemRemovedWithName": "{0} tasyǵyshhanadan alastaldy", + "LabelIpAddressValue": "IP-mekenjaıy: {0}", + "LabelRunningTimeValue": "Oınatý ýaqyty: {0}", + "Latest": "Eń keıingi", + "MessageApplicationUpdated": "Jellyfin Serveri jańartyldy", + "MessageApplicationUpdatedTo": "Jellyfin Serveri {0} deńgeıge jańartyldy", + "MessageNamedServerConfigurationUpdatedWithValue": "Server teńsheliminiń {0} bólimi jańartyldy", + "MessageServerConfigurationUpdated": "Server teńshelimi jańartyldy", + "MixedContent": "Aralas mazmun", + "Movies": "Fılmder", + "Music": "Mýzyka", + "MusicVideos": "Mýzykalyq beıneler", + "NameInstallFailed": "{0} ornatylýy sátsiz", + "NameSeasonNumber": "{0}-maýsym", + "NameSeasonUnknown": "Belgisiz maýsym", + "NewVersionIsAvailable": "Jańa Jellyfin Server nusqasy júktep alýǵa qoljetimdi.", + "NotificationOptionApplicationUpdateAvailable": "Qoldanba jańartýy qoljetimdi", + "NotificationOptionApplicationUpdateInstalled": "Qoldanba jańartýy ornatyldy", + "NotificationOptionAudioPlayback": "Dybys oınatýy bastaldy", + "NotificationOptionAudioPlaybackStopped": "Dybys oınatýy toqtatyldy", + "NotificationOptionCameraImageUploaded": "Kameradan fotosýret keri qotarylǵan", + "NotificationOptionInstallationFailed": "Ornatý sátsizdigi", + "NotificationOptionNewLibraryContent": "Jańa mazmun ústelgen", + "NotificationOptionPluginError": "Plagın sátsizdigi", + "NotificationOptionPluginInstalled": "Plagın ornatyldy", + "NotificationOptionPluginUninstalled": "Plagın ornatýy boldyrylmady", + "NotificationOptionPluginUpdateInstalled": "Plagın jańartýy ornatyldy", + "NotificationOptionServerRestartRequired": "Serverdi qaıta iske qosý qajet", + "NotificationOptionTaskFailed": "Josparlaǵan tapsyrma sátsizdigi", + "NotificationOptionUserLockedOut": "Paıdalanýshy qursaýly", + "NotificationOptionVideoPlayback": "Beıne oınatýy bastaldy", + "NotificationOptionVideoPlaybackStopped": "Beıne oınatýy toqtatyldy", + "Photos": "Fotosýretter", + "Playlists": "Oınatý tizimderi", + "Plugin": "Plagın", + "PluginInstalledWithName": "{0} ornatyldy", + "PluginUninstalledWithName": "{0} joıyldy", + "PluginUpdatedWithName": "{0} jańartyldy", + "ProviderValue": "Jetkizýshi: {0}", + "ScheduledTaskFailedWithName": "{0} sátsiz", + "ScheduledTaskStartedWithName": "{0} iske qosyldy", + "ServerNameNeedsToBeRestarted": "{0} qaıta iske qosý qajet", + "Shows": "Kórsetimder", + "Songs": "Áýender", + "StartupEmbyServerIsLoading": "Jellyfin Server júktelýde. Áreketti kóp uzamaı qaıtalańyz.", "SubtitleDownloadFailureForItem": "Субтитрлер {0} үшін жүктеліп алынуы сәтсіз", - "SubtitleDownloadFailureFromForItem": "{1} үшін субтитрлерді {0} көзінен жүктеп алу сәтсіз", - "SubtitlesDownloadedForItem": "{0} үшін субтитрлер жүктеліп алынды", - "Sync": "Үндестіру", - "System": "Жүйе", - "TvShows": "ТД-көрсетімдер", - "User": "Пайдаланушы", - "UserCreatedWithName": "Пайдаланушы {0} жасалған", - "UserDeletedWithName": "Пайдаланушы {0} жойылған", - "UserDownloadingItemWithValues": "{0} мынаны жүктеп алуда: {1}", - "UserLockedOutWithName": "Пайдаланушы {0} құрсаулы", - "UserOfflineFromDevice": "{0} - {1} тарапынан ажыратылған", - "UserOnlineFromDevice": "{0} - {1} арқылы қосылған", - "UserPasswordChangedWithName": "Пайдаланушы {0} үшін құпия сөз өзгертілді", - "UserPolicyUpdatedWithName": "Пайдаланушы {0} үшін саясаттары жаңартылды", - "UserStartedPlayingItemWithValues": "{0} - {1} ойнатуын {2} бастады", - "UserStoppedPlayingItemWithValues": "{0} - {1} ойнатуын {2} тоқтатты", - "ValueHasBeenAddedToLibrary": "{0} (тасығышханаға үстелінді)", - "ValueSpecialEpisodeName": "Арнайы - {0}", - "VersionNumber": "Нұсқасы: {0}" + "SubtitleDownloadFailureFromForItem": "{1} úshin sýbtıtrlerdi {0} kózinen júktep alý sátsiz", + "SubtitlesDownloadedForItem": "{0} úshin sýbtıtrler júktelip alyndy", + "Sync": "Úndestirý", + "System": "Júıe", + "TvShows": "TD-kórsetimder", + "User": "Paıdalanýshy", + "UserCreatedWithName": "Paıdalanýshy {0} jasalǵan", + "UserDeletedWithName": "Paıdalanýshy {0} joıylǵan", + "UserDownloadingItemWithValues": "{0} mynany júktep alýda: {1}", + "UserLockedOutWithName": "Paıdalanýshy {0} qursaýly", + "UserOfflineFromDevice": "{0} - {1} tarapynan ajyratylǵan", + "UserOnlineFromDevice": "{0} - {1} arqyly qosylǵan", + "UserPasswordChangedWithName": "Paıdalanýshy {0} úshin paról ózgertildi", + "UserPolicyUpdatedWithName": "Paıdalanýshy {0} úshin saıasattary jańartyldy", + "UserStartedPlayingItemWithValues": "{0} - {1} oınatýyn {2} bastady", + "UserStoppedPlayingItemWithValues": "{0} - {1} oınatýyn {2} toqtatty", + "ValueHasBeenAddedToLibrary": "{0} (tasyǵyshhanaǵa ústelindi)", + "ValueSpecialEpisodeName": "Arnaıy - {0}", + "VersionNumber": "Nusqasy: {0}" } From bfc3954995085e3d6beaa275cd7bf0e9fa85d419 Mon Sep 17 00:00:00 2001 From: Polydeukes Date: Sun, 10 Feb 2019 21:14:42 +0000 Subject: [PATCH 053/104] Translated using Weblate (Spanish) Currently translated at 100.0% (94 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/es/ --- .../Localization/Core/es.json | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/es.json b/Emby.Server.Implementations/Localization/Core/es.json index 5d118d21f2..1850b8f255 100644 --- a/Emby.Server.Implementations/Localization/Core/es.json +++ b/Emby.Server.Implementations/Localization/Core/es.json @@ -5,46 +5,46 @@ "Artists": "Artistas", "AuthenticationSucceededWithUserName": "{0} autenticado correctamente", "Books": "Libros", - "CameraImageUploadedFrom": "A new camera image has been uploaded from {0}", + "CameraImageUploadedFrom": "Se ha subido una nueva imagen de cámara desde {0}", "Channels": "Canales", "ChapterNameValue": "Capítulo {0}", "Collections": "Colecciones", "DeviceOfflineWithName": "{0} se ha desconectado", "DeviceOnlineWithName": "{0} está conectado", - "FailedLoginAttemptWithUserName": "Error al intentar iniciar sesión a partir de {0}", + "FailedLoginAttemptWithUserName": "Error al intentar iniciar sesión desde {0}", "Favorites": "Favoritos", "Folders": "Carpetas", "Genres": "Géneros", - "HeaderAlbumArtists": "Artistas del Álbum", - "HeaderCameraUploads": "Camera Uploads", + "HeaderAlbumArtists": "Artistas del álbum", + "HeaderCameraUploads": "Subidas desde cámara", "HeaderContinueWatching": "Continuar viendo", "HeaderFavoriteAlbums": "Álbumes favoritos", "HeaderFavoriteArtists": "Artistas favoritos", "HeaderFavoriteEpisodes": "Episodios favoritos", "HeaderFavoriteShows": "Programas favoritos", "HeaderFavoriteSongs": "Canciones favoritas", - "HeaderLiveTV": "TV en vivo", + "HeaderLiveTV": "TV en directo", "HeaderNextUp": "Siguiendo", "HeaderRecordingGroups": "Grupos de grabación", - "HomeVideos": "Vídeos de inicio", + "HomeVideos": "Vídeos caseros", "Inherit": "Heredar", "ItemAddedWithName": "{0} se ha añadido a la biblioteca", - "ItemRemovedWithName": "{0} se elimina de la biblioteca", + "ItemRemovedWithName": "{0} ha sido eliminado de la biblioteca", "LabelIpAddressValue": "Dirección IP: {0}", "LabelRunningTimeValue": "Tiempo de funcionamiento: {0}", "Latest": "Últimos", "MessageApplicationUpdated": "Se ha actualizado el servidor Jellyfin", - "MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}", - "MessageNamedServerConfigurationUpdatedWithValue": "La sección de configuración del servidor {0} ha sido actualizado", + "MessageApplicationUpdatedTo": "Se ha actualizado el servidor Jellyfin a la versión {0}", + "MessageNamedServerConfigurationUpdatedWithValue": "La sección {0} de configuración del servidor ha sido actualizada", "MessageServerConfigurationUpdated": "Se ha actualizado la configuración del servidor", "MixedContent": "Contenido mixto", - "Movies": "Peliculas", + "Movies": "Películas", "Music": "Música", - "MusicVideos": "Videos musicales", - "NameInstallFailed": "{0} installation failed", + "MusicVideos": "Vídeos musicales", + "NameInstallFailed": "{0} error de instalación", "NameSeasonNumber": "Temporada {0}", - "NameSeasonUnknown": "Season Unknown", - "NewVersionIsAvailable": "A new version of Jellyfin Server is available for download.", + "NameSeasonUnknown": "Temporada desconocida", + "NewVersionIsAvailable": "Disponible una nueva versión de Jellyfin para descargar.", "NotificationOptionApplicationUpdateAvailable": "Actualización de la aplicación disponible", "NotificationOptionApplicationUpdateInstalled": "Actualización de la aplicación instalada", "NotificationOptionAudioPlayback": "Se inició la reproducción de audio", @@ -56,13 +56,13 @@ "NotificationOptionPluginInstalled": "Plugin instalado", "NotificationOptionPluginUninstalled": "Plugin desinstalado", "NotificationOptionPluginUpdateInstalled": "Actualización del complemento instalada", - "NotificationOptionServerRestartRequired": "Requiere reinicio del servidor", + "NotificationOptionServerRestartRequired": "Se requiere reinicio del servidor", "NotificationOptionTaskFailed": "Error de tarea programada", "NotificationOptionUserLockedOut": "Usuario bloqueado", "NotificationOptionVideoPlayback": "Se inició la reproducción de vídeo", "NotificationOptionVideoPlaybackStopped": "Reproducción de vídeo detenida", "Photos": "Fotos", - "Playlists": "Listas reproducción", + "Playlists": "Listas de reproducción", "Plugin": "Plugin", "PluginInstalledWithName": "{0} se ha instalado", "PluginUninstalledWithName": "{0} se ha desinstalado", @@ -70,16 +70,16 @@ "ProviderValue": "Proveedor: {0}", "ScheduledTaskFailedWithName": "{0} falló", "ScheduledTaskStartedWithName": "{0} iniciada", - "ServerNameNeedsToBeRestarted": "{0} needs to be restarted", + "ServerNameNeedsToBeRestarted": "{0} necesita ser reiniciado", "Shows": "Series", "Songs": "Canciones", "StartupEmbyServerIsLoading": "Jellyfin Server se está cargando. Vuelve a intentarlo en breve.", "SubtitleDownloadFailureForItem": "Error al descargar subtítulos para {0}", - "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}", + "SubtitleDownloadFailureFromForItem": "Fallo de descarga de subtítulos desde {0} para {1}", "SubtitlesDownloadedForItem": "Descargar subtítulos para {0}", "Sync": "Sincronizar", "System": "Sistema", - "TvShows": "Series TV", + "TvShows": "Series de TV", "User": "Usuario", "UserCreatedWithName": "El usuario {0} ha sido creado", "UserDeletedWithName": "El usuario {0} ha sido borrado", @@ -88,10 +88,10 @@ "UserOfflineFromDevice": "{0} se ha desconectado de {1}", "UserOnlineFromDevice": "{0} está en línea desde {1}", "UserPasswordChangedWithName": "Se ha cambiado la contraseña para el usuario {0}", - "UserPolicyUpdatedWithName": "User policy has been updated for {0}", - "UserStartedPlayingItemWithValues": "{0} ha comenzado reproducir {1}", - "UserStoppedPlayingItemWithValues": "{0} ha parado de reproducir {1}", - "ValueHasBeenAddedToLibrary": "{0} has been added to your media library", + "UserPolicyUpdatedWithName": "Actualizada política de usuario para {0}", + "UserStartedPlayingItemWithValues": "{0} está reproduciendo {1} en {2}", + "UserStoppedPlayingItemWithValues": "{0} ha terminado de reproducir {1} en {2}", + "ValueHasBeenAddedToLibrary": "{0} ha sido añadido a tu biblioteca multimedia", "ValueSpecialEpisodeName": "Especial - {0}", "VersionNumber": "Versión {0}" } From af8f86b3debb157f31b5fdf36827994370375ae8 Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Wed, 13 Feb 2019 01:03:28 -0500 Subject: [PATCH 054/104] Bump version to 10.2.0~rc2 --- deployment/debian-package-x64/pkg-src/changelog | 10 +++++++--- deployment/fedora-package-x64/pkg-src/jellyfin.spec | 10 +++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/deployment/debian-package-x64/pkg-src/changelog b/deployment/debian-package-x64/pkg-src/changelog index d5872e4a7a..3db3f49531 100644 --- a/deployment/debian-package-x64/pkg-src/changelog +++ b/deployment/debian-package-x64/pkg-src/changelog @@ -1,4 +1,4 @@ -jellyfin (10.2.0~rc1) unstable; urgency=medium +jellyfin (10.2.0~rc2) unstable; urgency=medium * jellyfin: * PR452 Use EF Core for Activity database @@ -70,7 +70,10 @@ jellyfin (10.2.0~rc1) unstable; urgency=medium * PR842 Use VAAPI-enabled ffmpeg * PR852 Use SQLitePCL.pretty.netstandard on NuGet * PR853 Fix poor handling of cache directories - * PR8 rebase to latest master + * PR864: Add support for ZIP plugin archives + * PR868: Fix audio streaming via BaseProgressiveStreamingService + * PR869: Remove DLL support and require all packages/plugins to be zip archives + * PR872: Fix potential NullReferenceException * jellyfin-web: * PR24 Add Master codeowners * PR34 Revert "Add Master codeowners" @@ -91,12 +94,13 @@ jellyfin (10.2.0~rc1) unstable; urgency=medium * PR95 add display language option back * PR112 Removed seasonal theme support * PR116 Consolidate all strings into a single file per language + * PR117 Fix volume slider behavior * PR118 Enable and fix PiP for Safari * PR119 Make the toggle track visible on all themes * PR121 Fix syntax error in site.js * PR127 Change sharedcomponents module to core - -- Jellyfin Packaging Team Sun, 10 Feb 2019 01:18:23 -0500 + -- Jellyfin Packaging Team Sun, 13 Feb 2019 01:03:20 -0500 jellyfin (10.1.0-1) unstable; urgency=medium diff --git a/deployment/fedora-package-x64/pkg-src/jellyfin.spec b/deployment/fedora-package-x64/pkg-src/jellyfin.spec index 343d23e91e..4565c51112 100644 --- a/deployment/fedora-package-x64/pkg-src/jellyfin.spec +++ b/deployment/fedora-package-x64/pkg-src/jellyfin.spec @@ -8,7 +8,7 @@ Name: jellyfin Version: 10.2.0 -Release: rc1%{?dist} +Release: rc2%{?dist} Summary: The Free Software Media Browser License: GPLv2 URL: https://jellyfin.media @@ -140,7 +140,7 @@ fi %systemd_postun_with_restart jellyfin.service %changelog -* Sun Feb 10 2019 Jellyfin Packaging Team +* Wed Feb 13 2019 Jellyfin Packaging Team - jellyfin: - PR452 Use EF Core for Activity database - PR535 Clean up streambuilder @@ -211,7 +211,10 @@ fi - PR842 Use VAAPI-enabled ffmpeg - PR852 Use SQLitePCL.pretty.netstandard on NuGet - PR853 Fix poor handling of cache directories -- PR8 rebase to latest master +- PR864: Add support for ZIP plugin archives +- PR868: Fix audio streaming via BaseProgressiveStreamingService +- PR869: Remove DLL support and require all packages/plugins to be zip archives +- PR872: Fix potential NullReferenceException - jellyfin-web: - PR24 Add Master codeowners - PR34 Revert "Add Master codeowners" @@ -232,6 +235,7 @@ fi - PR95 add display language option back - PR112 Removed seasonal theme support - PR116 Consolidate all strings into a single file per language +- PR117 Fix volume slider behavior - PR118 Enable and fix PiP for Safari - PR119 Make the toggle track visible on all themes - PR121 Fix syntax error in site.js From 5835c4b21d5ab2666478f29c240d2e56316e1f67 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Wed, 13 Feb 2019 12:58:46 +0100 Subject: [PATCH 055/104] Remove comment --- Emby.Server.Implementations/Data/BaseSqliteRepository.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs index 556b7a547d..fba81306b3 100644 --- a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs +++ b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs @@ -364,7 +364,7 @@ namespace Emby.Server.Implementations.Data //{ // return new DummyToken(); //} - return new WriteLockToken(obj); // TODO: fix segfault + return new WriteLockToken(obj); } public static IDisposable Write(this ReaderWriterLockSlim obj) From a2dd2ddd55adc001bf3752dce6d4a95616e5dc4b Mon Sep 17 00:00:00 2001 From: ploughpuff <33969763+ploughpuff@users.noreply.github.com> Date: Wed, 13 Feb 2019 15:35:14 +0000 Subject: [PATCH 056/104] Rewrite rules for determining app paths and use XDG_CONFIG_HOME for configDir (#781) Re-write rules for determining dataDir, configDir and logDir. Generally, arguments from command line take precedence, then JELLYFIN env vars, before using XDG names. Co-Authored-By: ploughpuff <33969763+ploughpuff@users.noreply.github.com> --- .../AppBase/BaseApplicationPaths.cs | 103 +++-------- .../ServerApplicationPaths.cs | 15 +- Jellyfin.Server/Program.cs | 168 +++++++++++------- 3 files changed, 132 insertions(+), 154 deletions(-) diff --git a/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs b/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs index 701c04f9e2..f26cc4f62e 100644 --- a/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs +++ b/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs @@ -1,3 +1,4 @@ +using System; using System.IO; using MediaBrowser.Common.Configuration; @@ -14,50 +15,44 @@ namespace Emby.Server.Implementations.AppBase /// protected BaseApplicationPaths( string programDataPath, - string appFolderPath, - string logDirectoryPath = null, - string configurationDirectoryPath = null, - string cacheDirectoryPath = null) + string logDirectoryPath, + string configurationDirectoryPath, + string cacheDirectoryPath) { ProgramDataPath = programDataPath; - ProgramSystemPath = appFolderPath; LogDirectoryPath = logDirectoryPath; ConfigurationDirectoryPath = configurationDirectoryPath; CachePath = cacheDirectoryPath; + + DataPath = Path.Combine(ProgramDataPath, "data"); } + /// + /// Gets the path to the program data folder + /// + /// The program data path. public string ProgramDataPath { get; private set; } /// /// Gets the path to the system folder /// - public string ProgramSystemPath { get; private set; } + public string ProgramSystemPath { get; } = AppContext.BaseDirectory; - /// - /// The _data directory - /// - private string _dataDirectory; /// /// Gets the folder path to the data directory /// /// The data directory. + private string _dataPath; public string DataPath { - get - { - if (_dataDirectory == null) - { - _dataDirectory = Path.Combine(ProgramDataPath, "data"); - - Directory.CreateDirectory(_dataDirectory); - } - - return _dataDirectory; - } + get => _dataPath; + private set => _dataPath = Directory.CreateDirectory(value).FullName; } - private const string _virtualDataPath = "%AppDataPath%"; - public string VirtualDataPath => _virtualDataPath; + /// + /// Gets the magic strings used for virtual path manipulation. + /// + public string VirtualDataPath { get; } = "%AppDataPath%"; /// /// Gets the image cache path. @@ -83,55 +78,17 @@ namespace Emby.Server.Implementations.AppBase /// The plugin configurations path. public string TempUpdatePath => Path.Combine(ProgramDataPath, "updates"); - /// - /// The _log directory - /// - private string _logDirectoryPath; - /// /// Gets the path to the log directory /// /// The log directory path. - public string LogDirectoryPath - { - get - { - if (string.IsNullOrEmpty(_logDirectoryPath)) - { - _logDirectoryPath = Path.Combine(ProgramDataPath, "logs"); - - Directory.CreateDirectory(_logDirectoryPath); - } - - return _logDirectoryPath; - } - set => _logDirectoryPath = value; - } - - /// - /// The _config directory - /// - private string _configurationDirectoryPath; + public string LogDirectoryPath { get; private set; } /// /// Gets the path to the application configuration root directory /// /// The configuration directory path. - public string ConfigurationDirectoryPath - { - get - { - if (string.IsNullOrEmpty(_configurationDirectoryPath)) - { - _configurationDirectoryPath = Path.Combine(ProgramDataPath, "config"); - - Directory.CreateDirectory(_configurationDirectoryPath); - } - - return _configurationDirectoryPath; - } - set => _configurationDirectoryPath = value; - } + public string ConfigurationDirectoryPath { get; private set; } /// /// Gets the path to the system configuration file @@ -139,29 +96,11 @@ namespace Emby.Server.Implementations.AppBase /// The system configuration file path. public string SystemConfigurationFilePath => Path.Combine(ConfigurationDirectoryPath, "system.xml"); - /// - /// The _cache directory - /// - private string _cachePath; /// /// Gets the folder path to the cache directory /// /// The cache directory. - public string CachePath - { - get - { - if (string.IsNullOrEmpty(_cachePath)) - { - _cachePath = Path.Combine(ProgramDataPath, "cache"); - - Directory.CreateDirectory(_cachePath); - } - - return _cachePath; - } - set => _cachePath = value; - } + public string CachePath { get; set; } /// /// Gets the folder path to the temp directory within the cache folder diff --git a/Emby.Server.Implementations/ServerApplicationPaths.cs b/Emby.Server.Implementations/ServerApplicationPaths.cs index 36975df50c..05f6469ece 100644 --- a/Emby.Server.Implementations/ServerApplicationPaths.cs +++ b/Emby.Server.Implementations/ServerApplicationPaths.cs @@ -15,21 +15,17 @@ namespace Emby.Server.Implementations /// public ServerApplicationPaths( string programDataPath, - string appFolderPath, - string applicationResourcesPath, - string logDirectoryPath = null, - string configurationDirectoryPath = null, - string cacheDirectoryPath = null) + string logDirectoryPath, + string configurationDirectoryPath, + string cacheDirectoryPath) : base(programDataPath, - appFolderPath, logDirectoryPath, configurationDirectoryPath, cacheDirectoryPath) { - ApplicationResourcesPath = applicationResourcesPath; } - public string ApplicationResourcesPath { get; private set; } + public string ApplicationResourcesPath { get; } = AppContext.BaseDirectory; /// /// Gets the path to the base root media directory @@ -148,7 +144,6 @@ namespace Emby.Server.Implementations set => _internalMetadataPath = value; } - private const string _virtualInternalMetadataPath = "%MetadataPath%"; - public string VirtualInternalMetadataPath => _virtualInternalMetadataPath; + public string VirtualInternalMetadataPath { get; } = "%MetadataPath%"; } } diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 7826fde35b..6d372c36f4 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -139,112 +139,156 @@ namespace Jellyfin.Server } } + /// + /// Create the data, config and log paths from the variety of inputs(command line args, + /// environment variables) or decide on what default to use. For Windows it's %AppPath% + /// for everything else the XDG approach is followed: + /// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html + /// + /// + /// ServerApplicationPaths private static ServerApplicationPaths CreateApplicationPaths(StartupOptions options) { - string programDataPath = Environment.GetEnvironmentVariable("JELLYFIN_DATA_PATH"); - if (string.IsNullOrEmpty(programDataPath)) + // dataDir + // IF --datadir + // ELSE IF $JELLYFIN_DATA_PATH + // ELSE IF windows, use <%APPDATA%>/jellyfin + // ELSE IF $XDG_DATA_HOME then use $XDG_DATA_HOME/jellyfin + // ELSE use $HOME/.local/share/jellyfin + var dataDir = options.DataDir; + + if (string.IsNullOrEmpty(dataDir)) { - if (options.DataDir != null) - { - programDataPath = options.DataDir; - } - else + dataDir = Environment.GetEnvironmentVariable("JELLYFIN_DATA_PATH"); + + if (string.IsNullOrEmpty(dataDir)) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - programDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + dataDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); } else { // $XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored. - programDataPath = Environment.GetEnvironmentVariable("XDG_DATA_HOME"); - // If $XDG_DATA_HOME is either not set or empty, $HOME/.local/share should be used. - if (string.IsNullOrEmpty(programDataPath)) + dataDir = Environment.GetEnvironmentVariable("XDG_DATA_HOME"); + + // If $XDG_DATA_HOME is either not set or empty, a default equal to $HOME/.local/share should be used. + if (string.IsNullOrEmpty(dataDir)) { - programDataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share"); + dataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share"); } } - programDataPath = Path.Combine(programDataPath, "jellyfin"); + dataDir = Path.Combine(dataDir, "jellyfin"); } } - if (string.IsNullOrEmpty(programDataPath)) - { - Console.WriteLine("Cannot continue without path to program data folder (try -programdata)"); - Environment.Exit(1); - } - else - { - Directory.CreateDirectory(programDataPath); - } + // configDir + // IF --configdir + // ELSE IF $JELLYFIN_CONFIG_DIR + // ELSE IF --datadir, use /config (assume portable run) + // ELSE IF /config exists, use that + // ELSE IF windows, use /config + // ELSE IF $XDG_CONFIG_HOME use $XDG_CONFIG_HOME/jellyfin + // ELSE $HOME/.config/jellyfin + var configDir = options.ConfigDir; - string configDir = Environment.GetEnvironmentVariable("JELLYFIN_CONFIG_DIR"); if (string.IsNullOrEmpty(configDir)) { - if (options.ConfigDir != null) + configDir = Environment.GetEnvironmentVariable("JELLYFIN_CONFIG_DIR"); + + if (string.IsNullOrEmpty(configDir)) { - configDir = options.ConfigDir; - } - else - { - // Let BaseApplicationPaths set up the default value - configDir = null; + if (options.DataDir != null || Directory.Exists(Path.Combine(dataDir, "config")) || RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // Hang config folder off already set dataDir + configDir = Path.Combine(dataDir, "config"); + } + else + { + // $XDG_CONFIG_HOME defines the base directory relative to which user specific configuration files should be stored. + configDir = Environment.GetEnvironmentVariable("XDG_CONFIG_HOME"); + + // If $XDG_CONFIG_HOME is either not set or empty, a default equal to $HOME /.config should be used. + if (string.IsNullOrEmpty(configDir)) + { + configDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".config"); + } + + configDir = Path.Combine(configDir, "jellyfin"); + } } } - if (configDir != null) - { - Directory.CreateDirectory(configDir); - } + // cacheDir + // IF --cachedir + // ELSE IF $JELLYFIN_CACHE_DIR + // ELSE IF windows, use /cache + // ELSE IF XDG_CACHE_HOME, use $XDG_CACHE_HOME/jellyfin + // ELSE HOME/.cache/jellyfin + var cacheDir = options.CacheDir; - string cacheDir = Environment.GetEnvironmentVariable("JELLYFIN_CACHE_DIR"); if (string.IsNullOrEmpty(cacheDir)) { - if (options.CacheDir != null) + cacheDir = Environment.GetEnvironmentVariable("JELLYFIN_CACHE_DIR"); + + if (string.IsNullOrEmpty(cacheDir)) { - cacheDir = options.CacheDir; - } - else if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - // $XDG_CACHE_HOME defines the base directory relative to which user specific non-essential data files should be stored. - cacheDir = Environment.GetEnvironmentVariable("XDG_CACHE_HOME"); - // If $XDG_CACHE_HOME is either not set or empty, $HOME/.cache should be used. - if (string.IsNullOrEmpty(cacheDir)) + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { - cacheDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".cache"); + // Hang cache folder off already set dataDir + cacheDir = Path.Combine(dataDir, "cache"); + } + else + { + // $XDG_CACHE_HOME defines the base directory relative to which user specific non-essential data files should be stored. + cacheDir = Environment.GetEnvironmentVariable("XDG_CACHE_HOME"); + + // If $XDG_CACHE_HOME is either not set or empty, a default equal to $HOME/.cache should be used. + if (string.IsNullOrEmpty(cacheDir)) + { + cacheDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".cache"); + } + + cacheDir = Path.Combine(cacheDir, "jellyfin"); } - cacheDir = Path.Combine(cacheDir, "jellyfin"); } } - if (cacheDir != null) - { - Directory.CreateDirectory(cacheDir); - } + // logDir + // IF --logdir + // ELSE IF $JELLYFIN_LOG_DIR + // ELSE IF --datadir, use /log (assume portable run) + // ELSE /log + var logDir = options.LogDir; - string logDir = Environment.GetEnvironmentVariable("JELLYFIN_LOG_DIR"); if (string.IsNullOrEmpty(logDir)) { - if (options.LogDir != null) + logDir = Environment.GetEnvironmentVariable("JELLYFIN_LOG_DIR"); + + if (string.IsNullOrEmpty(logDir)) { - logDir = options.LogDir; - } - else - { - // Let BaseApplicationPaths set up the default value - logDir = null; + // Hang log folder off already set dataDir + logDir = Path.Combine(dataDir, "log"); } } - if (logDir != null) + // Ensure the main folders exist before we continue + try { + Directory.CreateDirectory(dataDir); Directory.CreateDirectory(logDir); + Directory.CreateDirectory(configDir); + Directory.CreateDirectory(cacheDir); + } + catch (IOException ex) + { + Console.Error.WriteLine("Error whilst attempting to create folder"); + Console.Error.WriteLine(ex.ToString()); + Environment.Exit(1); } - string appPath = AppContext.BaseDirectory; - - return new ServerApplicationPaths(programDataPath, appPath, appPath, logDir, configDir, cacheDir); + return new ServerApplicationPaths(dataDir, logDir, configDir, cacheDir); } private static async Task CreateLogger(IApplicationPaths appPaths) From c720504e39bae53c624f81b5df690e0088457789 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Wed, 13 Feb 2019 21:08:59 +0100 Subject: [PATCH 057/104] Drop ETag and use Last-Modified header (#890) Drop ETag and use Last-Modified since performance is much better --- .../HttpServer/HttpResultFactory.cs | 102 +++++------------- .../Net/StaticResultOptions.cs | 2 - 2 files changed, 24 insertions(+), 80 deletions(-) diff --git a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs index 7445fd3c28..75ca57ebb1 100644 --- a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -422,18 +422,20 @@ namespace Emby.Server.Implementations.HttpServer /// /// Pres the process optimized result. /// - private object GetCachedResult(IRequest requestContext, IDictionary responseHeaders, Guid cacheKey, string cacheKeyString, DateTime? lastDateModified, TimeSpan? cacheDuration, string contentType) + private object GetCachedResult(IRequest requestContext, IDictionary responseHeaders, StaticResultOptions options) { bool noCache = (requestContext.Headers.Get("Cache-Control") ?? string.Empty).IndexOf("no-cache", StringComparison.OrdinalIgnoreCase) != -1; + AddCachingHeaders(responseHeaders, options.CacheDuration, noCache, options.DateLastModified); if (!noCache) { - if (IsNotModified(requestContext, cacheKey)) - { - AddAgeHeader(responseHeaders, lastDateModified); - AddExpiresHeader(responseHeaders, cacheKeyString, cacheDuration); + DateTime.TryParse(requestContext.Headers.Get("If-Modified-Since"), out var ifModifiedSinceHeader); - var result = new HttpResult(Array.Empty(), contentType ?? "text/html", HttpStatusCode.NotModified); + if (IsNotModified(ifModifiedSinceHeader, options.CacheDuration, options.DateLastModified)) + { + AddAgeHeader(responseHeaders, options.DateLastModified); + + var result = new HttpResult(Array.Empty(), options.ContentType ?? "text/html", HttpStatusCode.NotModified); AddResponseHeaders(result, responseHeaders); @@ -441,8 +443,6 @@ namespace Emby.Server.Implementations.HttpServer } } - AddCachingHeaders(responseHeaders, cacheKeyString, cacheDuration); - return null; } @@ -487,9 +487,6 @@ namespace Emby.Server.Implementations.HttpServer options.DateLastModified = _fileSystem.GetLastWriteTimeUtc(path); } - var cacheKey = path + options.DateLastModified.Value.Ticks; - - options.CacheKey = cacheKey.GetMD5(); options.ContentFactory = () => Task.FromResult(GetFileStream(path, fileShare)); options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary(StringComparer.OrdinalIgnoreCase); @@ -520,7 +517,6 @@ namespace Emby.Server.Implementations.HttpServer return GetStaticResult(requestContext, new StaticResultOptions { CacheDuration = cacheDuration, - CacheKey = cacheKey, ContentFactory = factoryFn, ContentType = contentType, DateLastModified = lastDateModified, @@ -534,14 +530,10 @@ namespace Emby.Server.Implementations.HttpServer options.ResponseHeaders = options.ResponseHeaders ?? new Dictionary(StringComparer.OrdinalIgnoreCase); var contentType = options.ContentType; - var etag = requestContext.Headers.Get("If-None-Match"); - var cacheKey = etag != null ? new Guid(etag.Trim('\"')) : Guid.Empty; - if (!cacheKey.Equals(Guid.Empty)) + if (!string.IsNullOrEmpty(requestContext.Headers.Get("If-Modified-Since"))) { - var key = cacheKey.ToString("N"); - // See if the result is already cached in the browser - var result = GetCachedResult(requestContext, options.ResponseHeaders, cacheKey, key, options.DateLastModified, options.CacheDuration, contentType); + var result = GetCachedResult(requestContext, options.ResponseHeaders, options); if (result != null) { @@ -553,6 +545,8 @@ namespace Emby.Server.Implementations.HttpServer var isHeadRequest = options.IsHeadRequest || string.Equals(requestContext.Verb, "HEAD", StringComparison.OrdinalIgnoreCase); var factoryFn = options.ContentFactory; var responseHeaders = options.ResponseHeaders; + AddCachingHeaders(responseHeaders, options.CacheDuration, false, options.DateLastModified); + AddAgeHeader(responseHeaders, options.DateLastModified); var rangeHeader = requestContext.Headers.Get("Range"); @@ -566,21 +560,10 @@ namespace Emby.Server.Implementations.HttpServer }; AddResponseHeaders(hasHeaders, options.ResponseHeaders); - // Generate an ETag based on identifying information - TODO read contents from filesystem instead? - var responseId = $"{hasHeaders.ContentType}{options.Path}{hasHeaders.TotalContentLength}"; - var hashedId = MD5.Create().ComputeHash(Encoding.Default.GetBytes(responseId)); - hasHeaders.Headers["ETag"] = new Guid(hashedId).ToString("N"); - return hasHeaders; } var stream = await factoryFn().ConfigureAwait(false); - // Generate an etag based on stream content - var streamHash = MD5.Create().ComputeHash(stream); - var newEtag = new Guid(streamHash).ToString("N"); - - // reset position so the response can re-use it -- TODO is this ok? - stream.Position = 0; var totalContentLength = options.ContentLength; if (!totalContentLength.HasValue) @@ -603,7 +586,6 @@ namespace Emby.Server.Implementations.HttpServer }; AddResponseHeaders(hasHeaders, options.ResponseHeaders); - hasHeaders.Headers["ETag"] = newEtag; return hasHeaders; } else @@ -628,7 +610,6 @@ namespace Emby.Server.Implementations.HttpServer }; AddResponseHeaders(hasHeaders, options.ResponseHeaders); - hasHeaders.Headers["ETag"] = newEtag; return hasHeaders; } } @@ -641,37 +622,28 @@ namespace Emby.Server.Implementations.HttpServer /// /// Adds the caching responseHeaders. /// - private void AddCachingHeaders(IDictionary responseHeaders, string cacheKey, TimeSpan? cacheDuration) + private void AddCachingHeaders(IDictionary responseHeaders, TimeSpan? cacheDuration, + bool noCache, DateTime? lastModifiedDate) { - if (cacheDuration.HasValue) - { - responseHeaders["Cache-Control"] = "public, max-age=" + Convert.ToInt32(cacheDuration.Value.TotalSeconds); - } - else if (!string.IsNullOrEmpty(cacheKey)) - { - responseHeaders["Cache-Control"] = "public"; - } - else + if (noCache) { responseHeaders["Cache-Control"] = "no-cache, no-store, must-revalidate"; responseHeaders["pragma"] = "no-cache, no-store, must-revalidate"; + return; } - AddExpiresHeader(responseHeaders, cacheKey, cacheDuration); - } - - /// - /// Adds the expires header. - /// - private static void AddExpiresHeader(IDictionary responseHeaders, string cacheKey, TimeSpan? cacheDuration) - { if (cacheDuration.HasValue) { - responseHeaders["Expires"] = DateTime.UtcNow.Add(cacheDuration.Value).ToString("r"); + responseHeaders["Cache-Control"] = "public, max-age=" + cacheDuration.Value.TotalSeconds; } - else if (string.IsNullOrEmpty(cacheKey)) + else { - responseHeaders["Expires"] = "-1"; + responseHeaders["Cache-Control"] = "public"; + } + + if (lastModifiedDate.HasValue) + { + responseHeaders["Last-Modified"] = lastModifiedDate.ToString(); } } @@ -687,32 +659,6 @@ namespace Emby.Server.Implementations.HttpServer responseHeaders["Age"] = Convert.ToInt64((DateTime.UtcNow - lastDateModified.Value).TotalSeconds).ToString(CultureInfo.InvariantCulture); } } - /// - /// Determines whether [is not modified] [the specified cache key]. - /// - /// The request context. - /// The cache key. - /// The last date modified. - /// Duration of the cache. - /// true if [is not modified] [the specified cache key]; otherwise, false. - private bool IsNotModified(IRequest requestContext, Guid cacheKey) - { - var ifNoneMatchHeader = requestContext.Headers.Get("If-None-Match"); - - bool hasCacheKey = !cacheKey.Equals(Guid.Empty); - - // Validate If-None-Match - if (hasCacheKey && !string.IsNullOrEmpty(ifNoneMatchHeader)) - { - if (Guid.TryParse(ifNoneMatchHeader, out var ifNoneMatch) - && cacheKey.Equals(ifNoneMatch)) - { - return true; - } - } - - return false; - } /// /// Determines whether [is not modified] [the specified if modified since]. diff --git a/MediaBrowser.Controller/Net/StaticResultOptions.cs b/MediaBrowser.Controller/Net/StaticResultOptions.cs index a54de12be6..7a179913ac 100644 --- a/MediaBrowser.Controller/Net/StaticResultOptions.cs +++ b/MediaBrowser.Controller/Net/StaticResultOptions.cs @@ -12,8 +12,6 @@ namespace MediaBrowser.Controller.Net public string ContentType { get; set; } public TimeSpan? CacheDuration { get; set; } public DateTime? DateLastModified { get; set; } - public Guid CacheKey { get; set; } - public Func> ContentFactory { get; set; } public bool IsHeadRequest { get; set; } From a82303ccd146ce3093ccb29115aacc26b44bfbc4 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Wed, 13 Feb 2019 20:23:13 +0100 Subject: [PATCH 058/104] Fix uncaught xml error --- Emby.Dlna/PlayTo/Device.cs | 63 +++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/Emby.Dlna/PlayTo/Device.cs b/Emby.Dlna/PlayTo/Device.cs index 037cdd8aa7..b62c5e1d4c 100644 --- a/Emby.Dlna/PlayTo/Device.cs +++ b/Emby.Dlna/PlayTo/Device.cs @@ -4,6 +4,7 @@ using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; +using System.Xml; using System.Xml.Linq; using Emby.Dlna.Common; using Emby.Dlna.Server; @@ -733,26 +734,21 @@ namespace Emby.Dlna.PlayTo return (true, null); } - XElement uPnpResponse; + XElement uPnpResponse = null; - // Handle different variations sent back by devices try { - uPnpResponse = XElement.Parse(trackString); + uPnpResponse = ParseResponse(trackString); } - catch (Exception) + catch (Exception ex) { - // first try to add a root node with a dlna namesapce - try - { - uPnpResponse = XElement.Parse("" + trackString + ""); - uPnpResponse = uPnpResponse.Descendants().First(); - } - catch (Exception ex) - { - _logger.LogError(ex, "Unable to parse xml {0}", trackString); - return (true, null); - } + _logger.LogError(ex, "Uncaught exception while parsing xml"); + } + + if (uPnpResponse == null) + { + _logger.LogError("Failed to parse xml: \n {Xml}", trackString); + return (true, null); } var e = uPnpResponse.Element(uPnpNamespaces.items); @@ -762,6 +758,43 @@ namespace Emby.Dlna.PlayTo return (true, uTrack); } + private XElement ParseResponse(string xml) + { + // Handle different variations sent back by devices + try + { + return XElement.Parse(xml); + } + catch (XmlException) + { + + } + + // first try to add a root node with a dlna namesapce + try + { + return XElement.Parse("" + xml + "") + .Descendants() + .First(); + } + catch (XmlException) + { + + } + + // some devices send back invalid xml + try + { + return XElement.Parse(xml.Replace("&", "&")); + } + catch (XmlException) + { + + } + + return null; + } + private static uBaseObject CreateUBaseObject(XElement container, string trackUri) { if (container == null) From 7ec42b89a024011f7d183fb2566eb389f924a4f0 Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Wed, 13 Feb 2019 17:45:17 -0500 Subject: [PATCH 059/104] Correct changelogs for updated 10.2.0~rc2 --- deployment/debian-package-x64/pkg-src/changelog | 2 ++ deployment/fedora-package-x64/pkg-src/jellyfin.spec | 10 ++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/deployment/debian-package-x64/pkg-src/changelog b/deployment/debian-package-x64/pkg-src/changelog index 3db3f49531..a4b55a4ec2 100644 --- a/deployment/debian-package-x64/pkg-src/changelog +++ b/deployment/debian-package-x64/pkg-src/changelog @@ -74,6 +74,7 @@ jellyfin (10.2.0~rc2) unstable; urgency=medium * PR868: Fix audio streaming via BaseProgressiveStreamingService * PR869: Remove DLL support and require all packages/plugins to be zip archives * PR872: Fix potential NullReferenceException + * PR890: Drop ETag and use Last-Modified header * jellyfin-web: * PR24 Add Master codeowners * PR34 Revert "Add Master codeowners" @@ -99,6 +100,7 @@ jellyfin (10.2.0~rc2) unstable; urgency=medium * PR119 Make the toggle track visible on all themes * PR121 Fix syntax error in site.js * PR127 Change sharedcomponents module to core + * PR135 Make sure fallback culture is always available -- Jellyfin Packaging Team Sun, 13 Feb 2019 01:03:20 -0500 diff --git a/deployment/fedora-package-x64/pkg-src/jellyfin.spec b/deployment/fedora-package-x64/pkg-src/jellyfin.spec index 4565c51112..03fc0b6ff0 100644 --- a/deployment/fedora-package-x64/pkg-src/jellyfin.spec +++ b/deployment/fedora-package-x64/pkg-src/jellyfin.spec @@ -211,10 +211,11 @@ fi - PR842 Use VAAPI-enabled ffmpeg - PR852 Use SQLitePCL.pretty.netstandard on NuGet - PR853 Fix poor handling of cache directories -- PR864: Add support for ZIP plugin archives -- PR868: Fix audio streaming via BaseProgressiveStreamingService -- PR869: Remove DLL support and require all packages/plugins to be zip archives -- PR872: Fix potential NullReferenceException +- PR864 Add support for ZIP plugin archives +- PR868 Fix audio streaming via BaseProgressiveStreamingService +- PR869 Remove DLL support and require all packages/plugins to be zip archives +- PR872 Fix potential NullReferenceException +- PR890 Drop ETag and use Last-Modified header - jellyfin-web: - PR24 Add Master codeowners - PR34 Revert "Add Master codeowners" @@ -240,6 +241,7 @@ fi - PR119 Make the toggle track visible on all themes - PR121 Fix syntax error in site.js - PR127 Change sharedcomponents module to core +- PR135 Make sure fallback culture is always available * Sun Jan 20 2019 Jellyfin Packaging Team - jellyfin: - PR335 Build scripts and build system consolidation. From 5d4bef5478a55700f9e8b3dda5615881c81fd8cf Mon Sep 17 00:00:00 2001 From: Vasily Date: Thu, 14 Feb 2019 16:40:43 +0300 Subject: [PATCH 060/104] Update jellyfin-web submodule to master as of 14.02.2019 --- MediaBrowser.WebDashboard/jellyfin-web | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.WebDashboard/jellyfin-web b/MediaBrowser.WebDashboard/jellyfin-web index 094c1deae9..c7ce1ac8ec 160000 --- a/MediaBrowser.WebDashboard/jellyfin-web +++ b/MediaBrowser.WebDashboard/jellyfin-web @@ -1 +1 @@ -Subproject commit 094c1deae91c51b8bbf8ebb16a55758af110f04d +Subproject commit c7ce1ac8eccd50f1bd759b30fbe60ea797ffe86e From 8414285b588a41e50942deba171d852960b8907e Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Thu, 14 Feb 2019 09:15:37 -0500 Subject: [PATCH 061/104] Only modify Debian package spec for jellyfin-ffmpeg --- deployment/debian-package-x64/pkg-src/control | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/deployment/debian-package-x64/pkg-src/control b/deployment/debian-package-x64/pkg-src/control index 74bebeaf15..88d10438b4 100644 --- a/deployment/debian-package-x64/pkg-src/control +++ b/deployment/debian-package-x64/pkg-src/control @@ -18,6 +18,11 @@ Replaces: mediabrowser, emby, emby-server-beta, jellyfin-dev, emby-server Breaks: mediabrowser, emby, emby-server-beta, jellyfin-dev, emby-server Conflicts: mediabrowser, emby, emby-server-beta, jellyfin-dev, emby-server Architecture: any -Depends: at, libsqlite3-0, ffmpeg, libfontconfig1, libfreetype6, libssl1.0.0 | libssl1.0.2 +Depends: at, + libsqlite3-0, + ffmpeg (<7:4.1) | jellyfin-ffmpeg, + libfontconfig1, + libfreetype6, + libssl1.0.0 | libssl1.0.2 Description: Jellyfin is a home media server. It is built on top of other popular open source technologies such as Service Stack, jQuery, jQuery mobile, and Mono. It features a REST-based api with built-in documentation to facilitate client development. We also have client libraries for our api to enable rapid development. From dbebc4774f37231f308f55a76373735442f98ff9 Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Thu, 14 Feb 2019 20:06:20 +0100 Subject: [PATCH 062/104] Switched to Roslyn naming rules --- .editorconfig | 80 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 71 insertions(+), 9 deletions(-) diff --git a/.editorconfig b/.editorconfig index b2891188d8..141fd87a56 100644 --- a/.editorconfig +++ b/.editorconfig @@ -55,15 +55,77 @@ dotnet_style_prefer_conditional_expression_over_return = true:silent ############################### # Naming Conventions # ############################### -# Style Definitions -dotnet_naming_style.pascal_case_style.capitalization = pascal_case -# Use PascalCase for constant fields -dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion -dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields -dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style -dotnet_naming_symbols.constant_fields.applicable_kinds = field -dotnet_naming_symbols.constant_fields.applicable_accessibilities = * -dotnet_naming_symbols.constant_fields.required_modifiers = const +# Style Definitions (From Roslyn) + +# Non-private static fields are PascalCase +dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.symbols = non_private_static_fields +dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.style = non_private_static_field_style + +dotnet_naming_symbols.non_private_static_fields.applicable_kinds = field +dotnet_naming_symbols.non_private_static_fields.applicable_accessibilities = public, protected, internal, protected internal, private protected +dotnet_naming_symbols.non_private_static_fields.required_modifiers = static + +dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case + +# Constants are PascalCase +dotnet_naming_rule.constants_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants +dotnet_naming_rule.constants_should_be_pascal_case.style = constant_style + +dotnet_naming_symbols.constants.applicable_kinds = field, local +dotnet_naming_symbols.constants.required_modifiers = const + +dotnet_naming_style.constant_style.capitalization = pascal_case + +# Static fields are camelCase and start with s_ +dotnet_naming_rule.static_fields_should_be_camel_case.severity = suggestion +dotnet_naming_rule.static_fields_should_be_camel_case.symbols = static_fields +dotnet_naming_rule.static_fields_should_be_camel_case.style = static_field_style + +dotnet_naming_symbols.static_fields.applicable_kinds = field +dotnet_naming_symbols.static_fields.required_modifiers = static + +dotnet_naming_style.static_field_style.capitalization = camel_case +dotnet_naming_style.static_field_style.required_prefix = s_ + +# Instance fields are camelCase and start with _ +dotnet_naming_rule.instance_fields_should_be_camel_case.severity = suggestion +dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields +dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style + +dotnet_naming_symbols.instance_fields.applicable_kinds = field + +dotnet_naming_style.instance_field_style.capitalization = camel_case +dotnet_naming_style.instance_field_style.required_prefix = _ + +# Locals and parameters are camelCase +dotnet_naming_rule.locals_should_be_camel_case.severity = suggestion +dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters +dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style + +dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local + +dotnet_naming_style.camel_case_style.capitalization = camel_case + +# Local functions are PascalCase +dotnet_naming_rule.local_functions_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions +dotnet_naming_rule.local_functions_should_be_pascal_case.style = local_function_style + +dotnet_naming_symbols.local_functions.applicable_kinds = local_function + +dotnet_naming_style.local_function_style.capitalization = pascal_case + +# By default, name items with PascalCase +dotnet_naming_rule.members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members +dotnet_naming_rule.members_should_be_pascal_case.style = pascal_case_style + +dotnet_naming_symbols.all_members.applicable_kinds = * + +dotnet_naming_style.pascal_case_style.capitalization = pascal_case + ############################### # C# Coding Conventions # ############################### From db1ebe25591e0933731c7d7eb710127ee6aa6a6b Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Thu, 14 Feb 2019 20:14:29 +0100 Subject: [PATCH 063/104] Static fields prefix 's_' -> '_' --- .editorconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 141fd87a56..21f27df131 100644 --- a/.editorconfig +++ b/.editorconfig @@ -87,7 +87,7 @@ dotnet_naming_symbols.static_fields.applicable_kinds = field dotnet_naming_symbols.static_fields.required_modifiers = static dotnet_naming_style.static_field_style.capitalization = camel_case -dotnet_naming_style.static_field_style.required_prefix = s_ +dotnet_naming_style.static_field_style.required_prefix = _ # Instance fields are camelCase and start with _ dotnet_naming_rule.instance_fields_should_be_camel_case.severity = suggestion From 7bb8985f11569905af4edbf4c47cba4d9b32c7ca Mon Sep 17 00:00:00 2001 From: Anders Thomsen Date: Thu, 14 Feb 2019 21:53:04 +0100 Subject: [PATCH 064/104] Fix race condition in adding dlna devices to session when the device is discovered repeatedly --- Emby.Dlna/PlayTo/PlayToManager.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Emby.Dlna/PlayTo/PlayToManager.cs b/Emby.Dlna/PlayTo/PlayToManager.cs index 6cce312eef..28e70d0469 100644 --- a/Emby.Dlna/PlayTo/PlayToManager.cs +++ b/Emby.Dlna/PlayTo/PlayToManager.cs @@ -89,11 +89,6 @@ namespace Emby.Dlna.PlayTo return; } - if (_sessionManager.Sessions.Any(i => usn.IndexOf(i.DeviceId, StringComparison.OrdinalIgnoreCase) != -1)) - { - return; - } - var cancellationToken = _disposeCancellationTokenSource.Token; await _sessionLock.WaitAsync(cancellationToken).ConfigureAwait(false); @@ -105,6 +100,11 @@ namespace Emby.Dlna.PlayTo return; } + if (_sessionManager.Sessions.Any(i => usn.IndexOf(i.DeviceId, StringComparison.OrdinalIgnoreCase) != -1)) + { + return; + } + await AddDevice(info, location, cancellationToken).ConfigureAwait(false); } catch (OperationCanceledException) From c78298789d20eb91bd1d9729d7b590110ce744d5 Mon Sep 17 00:00:00 2001 From: WWWesten Date: Thu, 14 Feb 2019 13:40:33 +0000 Subject: [PATCH 065/104] Translated using Weblate (Kazakh) Currently translated at 100.0% (94 of 94 strings) Translation: Jellyfin/Jellyfin Translate-URL: https://translate.jellyfin.org/projects/jellyfin/jellyfin-core/kk/ --- Emby.Server.Implementations/Localization/Core/kk.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Emby.Server.Implementations/Localization/Core/kk.json b/Emby.Server.Implementations/Localization/Core/kk.json index a122f1f09a..658d168e9f 100644 --- a/Emby.Server.Implementations/Localization/Core/kk.json +++ b/Emby.Server.Implementations/Localization/Core/kk.json @@ -89,9 +89,9 @@ "UserOnlineFromDevice": "{0} - {1} arqyly qosylǵan", "UserPasswordChangedWithName": "Paıdalanýshy {0} úshin paról ózgertildi", "UserPolicyUpdatedWithName": "Paıdalanýshy {0} úshin saıasattary jańartyldy", - "UserStartedPlayingItemWithValues": "{0} - {1} oınatýyn {2} bastady", - "UserStoppedPlayingItemWithValues": "{0} - {1} oınatýyn {2} toqtatty", + "UserStartedPlayingItemWithValues": "{0} - {1} oınatýyn {2} bastady", + "UserStoppedPlayingItemWithValues": "{0} - {1} oınatýyn {2} toqtatty", "ValueHasBeenAddedToLibrary": "{0} (tasyǵyshhanaǵa ústelindi)", "ValueSpecialEpisodeName": "Arnaıy - {0}", - "VersionNumber": "Nusqasy: {0}" + "VersionNumber": "Nusqasy {0}" } From 2845e7e1017386e1069ac3c990af6256c073cea7 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Fri, 15 Feb 2019 08:56:08 +0100 Subject: [PATCH 066/104] Properly dispose HttpWebResponse when the request failed to avoid 'too many open files' --- .../HttpClientManager/HttpClientManager.cs | 38 +++++-------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs index 6ea1bd08e6..2232b3eebb 100644 --- a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs +++ b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs @@ -66,11 +66,6 @@ namespace Emby.Server.Implementations.HttpClientManager // http://stackoverflow.com/questions/566437/http-post-returns-the-error-417-expectation-failed-c ServicePointManager.Expect100Continue = false; - -#if NET46 -// Trakt requests sometimes fail without this - ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls; -#endif } /// @@ -106,23 +101,6 @@ namespace Emby.Server.Implementations.HttpClientManager return client; } - private static WebRequest CreateWebRequest(string url) - { - try - { - return WebRequest.Create(url); - } - catch (NotSupportedException) - { - //Webrequest creation does fail on MONO randomly when using WebRequest.Create - //the issue occurs in the GetCreator method here: http://www.oschina.net/code/explore/mono-2.8.1/mcs/class/System/System.Net/WebRequest.cs - - var type = Type.GetType("System.Net.HttpRequestCreator, System, Version=4.0.0.0,Culture=neutral, PublicKeyToken=b77a5c561934e089"); - var creator = Activator.CreateInstance(type, nonPublic: true) as IWebRequestCreate; - return creator.Create(new Uri(url)) as HttpWebRequest; - } - } - private WebRequest GetRequest(HttpRequestOptions options, string method) { string url = options.Url; @@ -135,7 +113,7 @@ namespace Emby.Server.Implementations.HttpClientManager url = url.Replace(userInfo + "@", string.Empty); } - var request = CreateWebRequest(url); + var request = WebRequest.Create(url); if (request is HttpWebRequest httpWebRequest) { @@ -627,14 +605,16 @@ namespace Emby.Server.Implementations.HttpClientManager var exception = new HttpException(webException.Message, webException); - var response = webException.Response as HttpWebResponse; - if (response != null) + using (var response = webException.Response as HttpWebResponse) { - exception.StatusCode = response.StatusCode; - - if ((int)response.StatusCode == 429) + if (response != null) { - client.LastTimeout = DateTime.UtcNow; + exception.StatusCode = response.StatusCode; + + if ((int)response.StatusCode == 429) + { + client.LastTimeout = DateTime.UtcNow; + } } } From 4018b7e2d506ec5d4f4a5670d198599e2381bd00 Mon Sep 17 00:00:00 2001 From: "Brian J. Murrell" Date: Thu, 14 Feb 2019 22:07:46 -0500 Subject: [PATCH 067/104] COPR auto building This adds enhancements so that Fedora/EL packages can be automatically built in COPR when a webhook is received. A typical webhook could be for tagging events for example or even a "Release" webhook to only build releases. --- .copr/Makefile | 9 +++ .../fedora-package-x64/create_tarball.sh | 55 +++++++++++++++++++ deployment/fedora-package-x64/package.sh | 47 +--------------- .../fedora-package-x64/pkg-src/jellyfin.spec | 2 +- 4 files changed, 66 insertions(+), 47 deletions(-) create mode 100644 .copr/Makefile create mode 100755 deployment/fedora-package-x64/create_tarball.sh diff --git a/.copr/Makefile b/.copr/Makefile new file mode 100644 index 0000000000..dbc7e4ad9d --- /dev/null +++ b/.copr/Makefile @@ -0,0 +1,9 @@ +srpm: + dnf -y install git + git submodule init + git submodule update + cd deployment/fedora-package-x64; \ + ./create_tarball.sh; \ + rpmbuild -bs pkg-src/jellyfin.spec \ + --define "_sourcedir $$PWD/pkg-src/" \ + --define "_srcrpmdir $(outdir)" diff --git a/deployment/fedora-package-x64/create_tarball.sh b/deployment/fedora-package-x64/create_tarball.sh new file mode 100755 index 0000000000..89a3a94752 --- /dev/null +++ b/deployment/fedora-package-x64/create_tarball.sh @@ -0,0 +1,55 @@ +#!/usr/bin/env bash + +# shellcheck disable=SC1091 +source ../common.build.sh + +WORKDIR="$( pwd )" +VERSION="$( sed -ne '/^Version:/s/.* *//p' "${WORKDIR}"/pkg-src/jellyfin.spec )" + +package_temporary_dir="${WORKDIR}/pkg-dist-tmp" +pkg_src_dir="${WORKDIR}/pkg-src" + +GNU_TAR=1 +echo "Bundling all sources for RPM build." +tar \ +--transform "s,^\.,jellyfin-${VERSION}," \ +--exclude='.git*' \ +--exclude='**/.git' \ +--exclude='**/.hg' \ +--exclude='**/.vs' \ +--exclude='**/.vscode' \ +--exclude='deployment' \ +--exclude='**/bin' \ +--exclude='**/obj' \ +--exclude='**/.nuget' \ +--exclude='*.deb' \ +--exclude='*.rpm' \ +-Jcf "$pkg_src_dir/jellyfin-${VERSION}.tar.xz" \ +-C "../.." ./ || GNU_TAR=0 + +if [ $GNU_TAR -eq 0 ]; then + echo "The installed tar binary did not support --transform. Using workaround." + mkdir -p "${package_temporary_dir}/jellyfin" + # Not GNU tar + tar \ + --exclude='.git*' \ + --exclude='**/.git' \ + --exclude='**/.hg' \ + --exclude='**/.vs' \ + --exclude='**/.vscode' \ + --exclude='deployment' \ + --exclude='**/bin' \ + --exclude='**/obj' \ + --exclude='**/.nuget' \ + --exclude='*.deb' \ + --exclude='*.rpm' \ + -zcf \ + "${package_temporary_dir}/jellyfin/jellyfin-${VERSION}.tar.gz" \ + -C "../.." ./ + echo "Extracting filtered package." + tar -Jzf "${package_temporary_dir}/jellyfin/jellyfin-${VERSION}.tar.gz" -C "${package_temporary_dir}/jellyfin-${VERSION}" + echo "Removing filtered package." + rm -f "${package_temporary_dir}/jellyfin/jellyfin-${VERSION}.tar.gz" + echo "Repackaging package into final tarball." + tar -Jzf "${pkg_src_dir}/jellyfin-${VERSION}.tar.gz" -C "${package_temporary_dir}" "jellyfin-${VERSION}" +fi diff --git a/deployment/fedora-package-x64/package.sh b/deployment/fedora-package-x64/package.sh index 74586417d9..eed29aef3c 100755 --- a/deployment/fedora-package-x64/package.sh +++ b/deployment/fedora-package-x64/package.sh @@ -21,52 +21,7 @@ else docker_sudo="" fi -# Create RPM source archive -GNU_TAR=1 -mkdir -p "${package_temporary_dir}" -echo "Bundling all sources for RPM build." -tar \ ---transform "s,^\.,jellyfin-${VERSION}," \ ---exclude='.git*' \ ---exclude='**/.git' \ ---exclude='**/.hg' \ ---exclude='**/.vs' \ ---exclude='**/.vscode' \ ---exclude='deployment' \ ---exclude='**/bin' \ ---exclude='**/obj' \ ---exclude='**/.nuget' \ ---exclude='*.deb' \ ---exclude='*.rpm' \ --czf "${pkg_src_dir}/jellyfin-${VERSION}.tar.gz" \ --C "../.." ./ || GNU_TAR=0 - -if [ $GNU_TAR -eq 0 ]; then - echo "The installed tar binary did not support --transform. Using workaround." - mkdir -p "${package_temporary_dir}/jellyfin" - # Not GNU tar - tar \ - --exclude='.git*' \ - --exclude='**/.git' \ - --exclude='**/.hg' \ - --exclude='**/.vs' \ - --exclude='**/.vscode' \ - --exclude='deployment' \ - --exclude='**/bin' \ - --exclude='**/obj' \ - --exclude='**/.nuget' \ - --exclude='*.deb' \ - --exclude='*.rpm' \ - -zcf \ - "${package_temporary_dir}/jellyfin/jellyfin-${VERSION}.tar.gz" \ - -C "../.." ./ - echo "Extracting filtered package." - tar -xzf "${package_temporary_dir}/jellyfin/jellyfin-${VERSION}.tar.gz" -C "${package_temporary_dir}/jellyfin-${VERSION}" - echo "Removing filtered package." - rm -f "${package_temporary_dir}/jellyfin/jellyfin-${VERSION}.tar.gz" - echo "Repackaging package into final tarball." - tar -czf "${pkg_src_dir}/jellyfin-${VERSION}.tar.gz" -C "${package_temporary_dir}" "jellyfin-${VERSION}" -fi +./create_tarball.sh # Set up the build environment Docker image ${docker_sudo} docker build ../.. -t "${image_name}" -f ./Dockerfile diff --git a/deployment/fedora-package-x64/pkg-src/jellyfin.spec b/deployment/fedora-package-x64/pkg-src/jellyfin.spec index 851c400445..262b9203aa 100644 --- a/deployment/fedora-package-x64/pkg-src/jellyfin.spec +++ b/deployment/fedora-package-x64/pkg-src/jellyfin.spec @@ -12,7 +12,7 @@ Release: 1%{?dist} Summary: The Free Software Media Browser License: GPLv2 URL: https://jellyfin.media -Source0: %{name}-%{version}.tar.gz +Source0: %{name}-%{version}.tar.xz Source1: jellyfin.service Source2: jellyfin.env Source3: jellyfin.sudoers From e33706ab251e830b6b8d8bb4ecade81a410a6542 Mon Sep 17 00:00:00 2001 From: "Brian J. Murrell" Date: Fri, 15 Feb 2019 08:50:31 -0500 Subject: [PATCH 068/104] Code review updates Also fix a bug in the tarball creation that existed even prior to moving it into create_tarball.sh --- .copr/Makefile | 3 +-- deployment/fedora-package-x64/create_tarball.sh | 8 ++++---- deployment/fedora-package-x64/pkg-src/jellyfin.spec | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.copr/Makefile b/.copr/Makefile index dbc7e4ad9d..84b98a0116 100644 --- a/.copr/Makefile +++ b/.copr/Makefile @@ -1,7 +1,6 @@ srpm: dnf -y install git - git submodule init - git submodule update + git submodule update --init --recursive cd deployment/fedora-package-x64; \ ./create_tarball.sh; \ rpmbuild -bs pkg-src/jellyfin.spec \ diff --git a/deployment/fedora-package-x64/create_tarball.sh b/deployment/fedora-package-x64/create_tarball.sh index 89a3a94752..e8301c9897 100755 --- a/deployment/fedora-package-x64/create_tarball.sh +++ b/deployment/fedora-package-x64/create_tarball.sh @@ -24,12 +24,12 @@ tar \ --exclude='**/.nuget' \ --exclude='*.deb' \ --exclude='*.rpm' \ --Jcf "$pkg_src_dir/jellyfin-${VERSION}.tar.xz" \ +-czf "$pkg_src_dir/jellyfin-${VERSION}.tar.gz" \ -C "../.." ./ || GNU_TAR=0 if [ $GNU_TAR -eq 0 ]; then echo "The installed tar binary did not support --transform. Using workaround." - mkdir -p "${package_temporary_dir}/jellyfin" + mkdir -p "${package_temporary_dir}/jellyfin"{,-"${VERSION}"} # Not GNU tar tar \ --exclude='.git*' \ @@ -47,9 +47,9 @@ if [ $GNU_TAR -eq 0 ]; then "${package_temporary_dir}/jellyfin/jellyfin-${VERSION}.tar.gz" \ -C "../.." ./ echo "Extracting filtered package." - tar -Jzf "${package_temporary_dir}/jellyfin/jellyfin-${VERSION}.tar.gz" -C "${package_temporary_dir}/jellyfin-${VERSION}" + tar -xzf "${package_temporary_dir}/jellyfin/jellyfin-${VERSION}.tar.gz" -C "${package_temporary_dir}/jellyfin-${VERSION}" echo "Removing filtered package." rm -f "${package_temporary_dir}/jellyfin/jellyfin-${VERSION}.tar.gz" echo "Repackaging package into final tarball." - tar -Jzf "${pkg_src_dir}/jellyfin-${VERSION}.tar.gz" -C "${package_temporary_dir}" "jellyfin-${VERSION}" + tar -czf "${pkg_src_dir}/jellyfin-${VERSION}.tar.gz" -C "${package_temporary_dir}" "jellyfin-${VERSION}" fi diff --git a/deployment/fedora-package-x64/pkg-src/jellyfin.spec b/deployment/fedora-package-x64/pkg-src/jellyfin.spec index 262b9203aa..851c400445 100644 --- a/deployment/fedora-package-x64/pkg-src/jellyfin.spec +++ b/deployment/fedora-package-x64/pkg-src/jellyfin.spec @@ -12,7 +12,7 @@ Release: 1%{?dist} Summary: The Free Software Media Browser License: GPLv2 URL: https://jellyfin.media -Source0: %{name}-%{version}.tar.xz +Source0: %{name}-%{version}.tar.gz Source1: jellyfin.service Source2: jellyfin.env Source3: jellyfin.sudoers From 21f0a7e020dab7b667559b8adc51a35147941d41 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Fri, 15 Feb 2019 23:05:14 +0100 Subject: [PATCH 069/104] Make all class implementing dynamically loaded interfaces public --- .../Channels/RefreshChannelsScheduledTask.cs | 2 +- .../EntryPoints/UserDataChangeNotifier.cs | 2 +- .../Library/Resolvers/SpecialFolderResolver.cs | 2 +- .../ScheduledTasks/Tasks/ChapterImagesTask.cs | 2 +- .../Sorting/AiredEpisodeOrderComparer.cs | 2 +- Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs | 2 +- MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs | 2 +- MediaBrowser.Api/System/ActivityLogWebSocketListener.cs | 2 +- MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs | 2 +- MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs | 2 +- MediaBrowser.Providers/Movies/MovieDbImageProvider.cs | 2 +- MediaBrowser.Providers/Music/MusicVideoMetadataService.cs | 2 +- MediaBrowser.Providers/Photos/PhotoAlbumMetadataService.cs | 2 +- MediaBrowser.Providers/Photos/PhotoMetadataService.cs | 2 +- MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs | 2 +- MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs | 2 +- MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs | 2 +- MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs | 2 +- 18 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs b/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs index 844f77a1ab..303a8ac7b1 100644 --- a/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs +++ b/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs @@ -10,7 +10,7 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Channels { - class RefreshChannelsScheduledTask : IScheduledTask, IConfigurableScheduledTask + public class RefreshChannelsScheduledTask : IScheduledTask, IConfigurableScheduledTask { private readonly IChannelManager _channelManager; private readonly IUserManager _userManager; diff --git a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs index 774ed09dab..a5badaceec 100644 --- a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs @@ -14,7 +14,7 @@ using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.EntryPoints { - class UserDataChangeNotifier : IServerEntryPoint + public class UserDataChangeNotifier : IServerEntryPoint { private readonly ISessionManager _sessionManager; private readonly ILogger _logger; diff --git a/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs b/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs index fa8c89e88d..7e4b38b4c0 100644 --- a/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs @@ -9,7 +9,7 @@ using MediaBrowser.Model.IO; namespace Emby.Server.Implementations.Library.Resolvers { - class SpecialFolderResolver : FolderResolver + public class SpecialFolderResolver : FolderResolver { private readonly IFileSystem _fileSystem; private readonly IServerApplicationPaths _appPaths; diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs index 81fdb96d2f..2f07ff15a9 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs @@ -21,7 +21,7 @@ namespace Emby.Server.Implementations.ScheduledTasks /// /// Class ChapterImagesTask /// - class ChapterImagesTask : IScheduledTask + public class ChapterImagesTask : IScheduledTask { /// /// The _logger diff --git a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs index 271188314c..16507466f9 100644 --- a/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs +++ b/Emby.Server.Implementations/Sorting/AiredEpisodeOrderComparer.cs @@ -6,7 +6,7 @@ using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Sorting { - class AiredEpisodeOrderComparer : IBaseItemComparer + public class AiredEpisodeOrderComparer : IBaseItemComparer { /// /// Compares the specified x. diff --git a/Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs b/Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs index 942e847041..46e0dd9186 100644 --- a/Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs +++ b/Emby.Server.Implementations/Sorting/SeriesSortNameComparer.cs @@ -5,7 +5,7 @@ using MediaBrowser.Model.Querying; namespace Emby.Server.Implementations.Sorting { - class SeriesSortNameComparer : IBaseItemComparer + public class SeriesSortNameComparer : IBaseItemComparer { /// /// Compares the specified x. diff --git a/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs b/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs index 387ccad25e..beb2fb11d0 100644 --- a/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs +++ b/MediaBrowser.Api/Session/SessionInfoWebSocketListener.cs @@ -11,7 +11,7 @@ namespace MediaBrowser.Api.Session /// /// Class SessionInfoWebSocketListener /// - class SessionInfoWebSocketListener : BasePeriodicWebSocketListener, WebSocketListenerState> + public class SessionInfoWebSocketListener : BasePeriodicWebSocketListener, WebSocketListenerState> { /// /// Gets the name. diff --git a/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs b/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs index 0df46c3996..43f3c5a223 100644 --- a/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs +++ b/MediaBrowser.Api/System/ActivityLogWebSocketListener.cs @@ -11,7 +11,7 @@ namespace MediaBrowser.Api.System /// /// Class SessionInfoWebSocketListener /// - class ActivityLogWebSocketListener : BasePeriodicWebSocketListener, WebSocketListenerState> + public class ActivityLogWebSocketListener : BasePeriodicWebSocketListener, WebSocketListenerState> { /// /// Gets the name. diff --git a/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs b/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs index 4180a4f153..442a18cb98 100644 --- a/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs +++ b/MediaBrowser.LocalMetadata/Providers/PlaylistXmlProvider.cs @@ -9,7 +9,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.LocalMetadata.Providers { - class PlaylistXmlProvider : BaseXmlProvider + public class PlaylistXmlProvider : BaseXmlProvider { private readonly ILogger _logger; private readonly IProviderManager _providerManager; diff --git a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs index c6c1a2a945..4d12b2f4ab 100644 --- a/MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs +++ b/MediaBrowser.Providers/BoxSets/MovieDbBoxSetImageProvider.cs @@ -14,7 +14,7 @@ using MediaBrowser.Providers.Movies; namespace MediaBrowser.Providers.BoxSets { - class MovieDbBoxSetImageProvider : IRemoteImageProvider, IHasOrder + public class MovieDbBoxSetImageProvider : IRemoteImageProvider, IHasOrder { private readonly IHttpClient _httpClient; diff --git a/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs b/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs index b9c5d7ce59..20b53d58ad 100644 --- a/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs +++ b/MediaBrowser.Providers/Movies/MovieDbImageProvider.cs @@ -16,7 +16,7 @@ using MediaBrowser.Model.Serialization; namespace MediaBrowser.Providers.Movies { - class MovieDbImageProvider : IRemoteImageProvider, IHasOrder + public class MovieDbImageProvider : IRemoteImageProvider, IHasOrder { private readonly IJsonSerializer _jsonSerializer; private readonly IHttpClient _httpClient; diff --git a/MediaBrowser.Providers/Music/MusicVideoMetadataService.cs b/MediaBrowser.Providers/Music/MusicVideoMetadataService.cs index 8b01ff3427..93412306fc 100644 --- a/MediaBrowser.Providers/Music/MusicVideoMetadataService.cs +++ b/MediaBrowser.Providers/Music/MusicVideoMetadataService.cs @@ -9,7 +9,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Providers.Music { - class MusicVideoMetadataService : MetadataService + public class MusicVideoMetadataService : MetadataService { protected override void MergeData(MetadataResult source, MetadataResult target, MetadataFields[] lockedFields, bool replaceData, bool mergeMetadataSettings) { diff --git a/MediaBrowser.Providers/Photos/PhotoAlbumMetadataService.cs b/MediaBrowser.Providers/Photos/PhotoAlbumMetadataService.cs index fd969c7c29..993581cca8 100644 --- a/MediaBrowser.Providers/Photos/PhotoAlbumMetadataService.cs +++ b/MediaBrowser.Providers/Photos/PhotoAlbumMetadataService.cs @@ -9,7 +9,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Providers.Photos { - class PhotoAlbumMetadataService : MetadataService + public class PhotoAlbumMetadataService : MetadataService { protected override void MergeData(MetadataResult source, MetadataResult target, MetadataFields[] lockedFields, bool replaceData, bool mergeMetadataSettings) { diff --git a/MediaBrowser.Providers/Photos/PhotoMetadataService.cs b/MediaBrowser.Providers/Photos/PhotoMetadataService.cs index a430e1041d..b739c57654 100644 --- a/MediaBrowser.Providers/Photos/PhotoMetadataService.cs +++ b/MediaBrowser.Providers/Photos/PhotoMetadataService.cs @@ -9,7 +9,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Providers.Photos { - class PhotoMetadataService : MetadataService + public class PhotoMetadataService : MetadataService { protected override void MergeData(MetadataResult source, MetadataResult target, MetadataFields[] lockedFields, bool replaceData, bool mergeMetadataSettings) { diff --git a/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs b/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs index b28d2a5489..30ce5c64ca 100644 --- a/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs +++ b/MediaBrowser.Providers/Playlists/PlaylistMetadataService.cs @@ -11,7 +11,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Providers.Playlists { - class PlaylistMetadataService : MetadataService + public class PlaylistMetadataService : MetadataService { protected override IList GetChildrenForMetadataUpdates(Playlist item) { diff --git a/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs b/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs index d0749405b4..dee3030af1 100644 --- a/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/Omdb/OmdbEpisodeProvider.cs @@ -16,7 +16,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Providers.TV.Omdb { - class OmdbEpisodeProvider : + public class OmdbEpisodeProvider : IRemoteMetadataProvider, IHasOrder { diff --git a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs index 44590515ee..3d77450859 100644 --- a/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs +++ b/MediaBrowser.Providers/TV/TheMovieDb/MovieDbEpisodeProvider.cs @@ -20,7 +20,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.Providers.TV.TheMovieDb { - class MovieDbEpisodeProvider : + public class MovieDbEpisodeProvider : MovieDbProviderBase, IRemoteMetadataProvider, IHasOrder diff --git a/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs index 21ee8f92f4..a3e48d30d9 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/MovieNfoParser.cs @@ -13,7 +13,7 @@ using Microsoft.Extensions.Logging; namespace MediaBrowser.XbmcMetadata.Parsers { - class MovieNfoParser : BaseNfoParser /// The receive action. public Action OnReceiveBytes { get; set; } - - /// - /// Gets or sets the on receive. - /// - /// The on receive. - public Action OnReceive { get; set; } } } diff --git a/Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs b/Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs index a0ffd1ccf4..4b6649217b 100644 --- a/Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs +++ b/Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs @@ -201,7 +201,7 @@ namespace Jellyfin.Server.SocketSharp } catch (ObjectDisposedException) { - //TODO Investigate and properly fix. + // TODO: Investigate and properly fix. } catch (Exception ex) { @@ -252,7 +252,7 @@ namespace Jellyfin.Server.SocketSharp Stop(); } - //release unmanaged resources here... + // release unmanaged resources here... _disposed = true; } } diff --git a/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs b/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs index ebeb18ea06..37fc6fe12d 100644 --- a/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs +++ b/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs @@ -24,7 +24,7 @@ namespace Jellyfin.Server.SocketSharp this.request = httpContext.Request; this.response = new WebSocketSharpResponse(logger, httpContext.Response, this); - //HandlerFactoryPath = GetHandlerPathIfAny(UrlPrefixes[0]); + // HandlerFactoryPath = GetHandlerPathIfAny(UrlPrefixes[0]); } private static string GetHandlerPathIfAny(string listenerUrl) diff --git a/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs b/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs index cabc96b237..68995a819e 100644 --- a/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs +++ b/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs @@ -51,7 +51,7 @@ namespace Jellyfin.Server.SocketSharp set => _response.ContentType = value; } - //public ICookies Cookies { get; set; } + // public ICookies Cookies { get; set; } public void AddHeader(string name, string value) { @@ -114,9 +114,9 @@ namespace Jellyfin.Server.SocketSharp public void SetContentLength(long contentLength) { - //you can happily set the Content-Length header in Asp.Net - //but HttpListener will complain if you do - you have to set ContentLength64 on the response. - //workaround: HttpListener throws "The parameter is incorrect" exceptions when we try to set the Content-Length header + // you can happily set the Content-Length header in Asp.Net + // but HttpListener will complain if you do - you have to set ContentLength64 on the response. + // workaround: HttpListener throws "The parameter is incorrect" exceptions when we try to set the Content-Length header _response.ContentLength64 = contentLength; } @@ -147,10 +147,6 @@ namespace Jellyfin.Server.SocketSharp { sb.Append($";domain={cookie.Domain}"); } - //else if (restrictAllCookiesToDomain != null) - //{ - // sb.Append($";domain={restrictAllCookiesToDomain}"); - //} if (cookie.Secure) { From d8b312674db11b59c90747c5d2510ed25ec40b06 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Wed, 13 Feb 2019 16:54:37 +0100 Subject: [PATCH 073/104] No multiple empty lines --- Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs b/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs index 68995a819e..a4e6aac351 100644 --- a/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs +++ b/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs @@ -13,7 +13,6 @@ using HttpListenerResponse = SocketHttpListener.Net.HttpListenerResponse; using IHttpResponse = MediaBrowser.Model.Services.IHttpResponse; using IRequest = MediaBrowser.Model.Services.IRequest; - namespace Jellyfin.Server.SocketSharp { public class WebSocketSharpResponse : IHttpResponse @@ -160,7 +159,6 @@ namespace Jellyfin.Server.SocketSharp return sb.ToString(); } - public bool SendChunked { get => _response.SendChunked; From fc59b0ab77b60cb9d06a5027ee0f2363e39fbea7 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Wed, 13 Feb 2019 16:57:55 +0100 Subject: [PATCH 074/104] Disable SA1512 --- jellyfin.ruleset | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jellyfin.ruleset b/jellyfin.ruleset index 0f8c9aa020..295a45dc94 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -7,6 +7,8 @@ + + From 637936cb9f2734df8e7c4c5838430bf5069901e6 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Wed, 13 Feb 2019 16:59:30 +0100 Subject: [PATCH 075/104] Closing braces should be followed by an empty line --- Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs | 3 +++ Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs | 1 + 2 files changed, 4 insertions(+) diff --git a/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs b/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs index 37fc6fe12d..a0f9e6d2d2 100644 --- a/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs +++ b/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs @@ -140,10 +140,12 @@ namespace Jellyfin.Server.SocketSharp throw new ArgumentException("net_WebHeaderInvalidCRLFChars"); } } + if (crlf != 0) { throw new ArgumentException("net_WebHeaderInvalidCRLFChars"); } + return name; } @@ -156,6 +158,7 @@ namespace Jellyfin.Server.SocketSharp return true; } } + return false; } diff --git a/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs b/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs index a4e6aac351..6de678b86c 100644 --- a/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs +++ b/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs @@ -151,6 +151,7 @@ namespace Jellyfin.Server.SocketSharp { sb.Append(";Secure"); } + if (cookie.HttpOnly) { sb.Append(";HttpOnly"); From 183ef34422656468a9e145f37ed4be7a70823194 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Wed, 13 Feb 2019 17:03:50 +0100 Subject: [PATCH 076/104] Do not declare visible instance fields --- Jellyfin.Server/SocketSharp/RequestMono.cs | 8 ++++++-- Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/Jellyfin.Server/SocketSharp/RequestMono.cs b/Jellyfin.Server/SocketSharp/RequestMono.cs index af8fe96167..4bb2e8e190 100644 --- a/Jellyfin.Server/SocketSharp/RequestMono.cs +++ b/Jellyfin.Server/SocketSharp/RequestMono.cs @@ -127,8 +127,12 @@ namespace Jellyfin.Server.SocketSharp public string Authorization => string.IsNullOrEmpty(request.Headers["Authorization"]) ? null : request.Headers["Authorization"]; - protected bool validate_cookies, validate_query_string, validate_form; - protected bool checked_cookies, checked_query_string, checked_form; + protected bool validate_cookies { get; set; } + protected bool validate_query_string { get; set; } + protected bool validate_form { get; set; } + protected bool checked_cookies { get; set; } + protected bool checked_query_string { get; set; } + protected bool checked_form { get; set; } private static void ThrowValidationException(string name, string key, string value) { diff --git a/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs b/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs index a0f9e6d2d2..c5fdf6a3b0 100644 --- a/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs +++ b/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs @@ -447,7 +447,7 @@ namespace Jellyfin.Server.SocketSharp public string ContentType => request.ContentType; - public Encoding contentEncoding; + private Encoding contentEncoding; public Encoding ContentEncoding { get => contentEncoding ?? request.ContentEncoding; From 34af7501fa33f807aa7e721a95294b623f2d4d6c Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Wed, 13 Feb 2019 17:06:32 +0100 Subject: [PATCH 077/104] Fix up CoreAppHost.cs --- Jellyfin.Server/CoreAppHost.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index a486c2a475..126cb467f9 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -18,6 +18,8 @@ namespace Jellyfin.Server public override bool CanSelfRestart => StartupOptions.RestartPath != null; + protected override bool SupportsDualModeSockets => true; + protected override void RestartInternal() => Program.Restart(); protected override IEnumerable GetAssembliesWithPartsInternal() @@ -27,8 +29,6 @@ namespace Jellyfin.Server protected override void ShutdownInternal() => Program.Shutdown(); - protected override bool SupportsDualModeSockets => true; - protected override IHttpListener CreateHttpListener() => new WebSocketSharpListener( Logger, @@ -39,7 +39,6 @@ namespace Jellyfin.Server CryptographyProvider, SupportsDualModeSockets, FileSystemManager, - EnvironmentInfo - ); + EnvironmentInfo); } } From be77e14db96b709fc0dc212258c3389a210e1af4 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Wed, 13 Feb 2019 17:19:55 +0100 Subject: [PATCH 078/104] Warnings for docs --- Jellyfin.Server/Jellyfin.Server.csproj | 3 ++ Jellyfin.Server/Program.cs | 40 ++++++++++--------- Jellyfin.Server/SocketSharp/RequestMono.cs | 2 - Jellyfin.Server/SocketSharp/SharpWebSocket.cs | 1 + 4 files changed, 26 insertions(+), 20 deletions(-) diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index fe1397bcbe..a6bf23f5be 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -5,11 +5,14 @@ Exe netcoreapp2.1 false + true latest + + SA1600 diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 6dfabc3644..ac5aab4609 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -57,6 +57,21 @@ namespace Jellyfin.Server errs => Task.FromResult(0)).ConfigureAwait(false); } + public static void Shutdown() + { + if (!_tokenSource.IsCancellationRequested) + { + _tokenSource.Cancel(); + } + } + + public static void Restart() + { + _restartOnShutdown = true; + + Shutdown(); + } + private static async Task StartApp(StartupOptions options) { ServerApplicationPaths appPaths = CreateApplicationPaths(options); @@ -76,6 +91,7 @@ namespace Jellyfin.Server { return; // Already shutting down } + e.Cancel = true; _logger.LogInformation("Ctrl+C, shutting down"); Environment.ExitCode = 128 + 2; @@ -89,6 +105,7 @@ namespace Jellyfin.Server { return; // Already shutting down } + _logger.LogInformation("Received a SIGTERM signal, shutting down"); Environment.ExitCode = 128 + 15; Shutdown(); @@ -102,7 +119,7 @@ namespace Jellyfin.Server SQLitePCL.Batteries_V2.Init(); // Allow all https requests - ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; }); + ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; } ); var fileSystem = new ManagedFileSystem(_loggerFactory, environmentInfo, null, appPaths.TempDirectory, true); @@ -146,7 +163,7 @@ namespace Jellyfin.Server /// for everything else the XDG approach is followed: /// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html /// - /// + /// StartupOptions /// ServerApplicationPaths private static ServerApplicationPaths CreateApplicationPaths(StartupOptions options) { @@ -308,6 +325,7 @@ namespace Jellyfin.Server await rscstr.CopyToAsync(fstr).ConfigureAwait(false); } } + var configuration = new ConfigurationBuilder() .SetBasePath(appPaths.ConfigurationDirectoryPath) .AddJsonFile("logging.json") @@ -335,7 +353,7 @@ namespace Jellyfin.Server } } - public static IImageEncoder GetImageEncoder( + private static IImageEncoder GetImageEncoder( IFileSystem fileSystem, IApplicationPaths appPaths, ILocalizationManager localizationManager) @@ -376,26 +394,12 @@ namespace Jellyfin.Server { return MediaBrowser.Model.System.OperatingSystem.BSD; } + throw new Exception($"Can't resolve OS with description: '{osDescription}'"); } } } - public static void Shutdown() - { - if (!_tokenSource.IsCancellationRequested) - { - _tokenSource.Cancel(); - } - } - - public static void Restart() - { - _restartOnShutdown = true; - - Shutdown(); - } - private static void StartNewInstance(StartupOptions options) { _logger.LogInformation("Starting new instance"); diff --git a/Jellyfin.Server/SocketSharp/RequestMono.cs b/Jellyfin.Server/SocketSharp/RequestMono.cs index 4bb2e8e190..584d38bcbc 100644 --- a/Jellyfin.Server/SocketSharp/RequestMono.cs +++ b/Jellyfin.Server/SocketSharp/RequestMono.cs @@ -82,9 +82,7 @@ namespace Jellyfin.Server.SocketSharp } else { - // // We use a substream, as in 2.x we will support large uploads streamed to disk, - // var sub = new HttpPostedFile(e.Filename, e.ContentType, input, e.Start, e.Length); files[e.Name] = sub; } diff --git a/Jellyfin.Server/SocketSharp/SharpWebSocket.cs b/Jellyfin.Server/SocketSharp/SharpWebSocket.cs index e7e36e31be..5b233cdf5d 100644 --- a/Jellyfin.Server/SocketSharp/SharpWebSocket.cs +++ b/Jellyfin.Server/SocketSharp/SharpWebSocket.cs @@ -55,6 +55,7 @@ namespace Jellyfin.Server.SocketSharp void socket_OnError(object sender, SocketHttpListener.ErrorEventArgs e) { _logger.LogError("Error in SharpWebSocket: {Message}", e.Message ?? string.Empty); + // Closed?.Invoke(this, EventArgs.Empty); } From 892787cb1a72303ffd514971d0d5ea4c30f2dcd1 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Wed, 13 Feb 2019 17:25:47 +0100 Subject: [PATCH 079/104] Disable SA1130 --- jellyfin.ruleset | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jellyfin.ruleset b/jellyfin.ruleset index 295a45dc94..25d11d7d35 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -3,6 +3,8 @@ + + From 46897aab4f85bd2ea50e0ff1ef57c0cfa8f48c67 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Wed, 13 Feb 2019 17:28:04 +0100 Subject: [PATCH 080/104] More warnings --- Jellyfin.Server/SocketSharp/RequestMono.cs | 9 ++------- Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs | 7 +++++-- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Jellyfin.Server/SocketSharp/RequestMono.cs b/Jellyfin.Server/SocketSharp/RequestMono.cs index 584d38bcbc..9a06017501 100644 --- a/Jellyfin.Server/SocketSharp/RequestMono.cs +++ b/Jellyfin.Server/SocketSharp/RequestMono.cs @@ -431,13 +431,13 @@ namespace Jellyfin.Server.SocketSharp real = position + d; break; default: - throw new ArgumentException(nameof(origin)); + throw new ArgumentException("Unknown SeekOrigin value", nameof(origin)); } long virt = real - offset; if (virt < 0 || virt > Length) { - throw new ArgumentException(); + throw new ArgumentException("Invalid position", nameof(origin)); } position = s.Seek(real, SeekOrigin.Begin); @@ -572,11 +572,6 @@ namespace Jellyfin.Server.SocketSharp public HttpMultipart(Stream data, string b, Encoding encoding) { this.data = data; - // DB: 30/01/11: cannot set or read the Position in HttpListener in Win.NET - // var ms = new MemoryStream(32 * 1024); - // data.CopyTo(ms); - // this.data = ms; - boundary = b; boundary_bytes = encoding.GetBytes(b); buffer = new byte[boundary_bytes.Length + 2]; // CRLF or '--' diff --git a/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs b/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs index c5fdf6a3b0..a19ea6bf7a 100644 --- a/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs +++ b/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Text; using Emby.Server.Implementations.HttpServer; @@ -69,9 +70,11 @@ namespace Jellyfin.Server.SocketSharp public string UserHostAddress => request.UserHostAddress; - public string XForwardedFor => string.IsNullOrEmpty(request.Headers["X-Forwarded-For"]) ? null : request.Headers["X-Forwarded-For"]; + public string XForwardedFor + => string.IsNullOrEmpty(request.Headers["X-Forwarded-For"]) ? null : request.Headers["X-Forwarded-For"]; - public int? XForwardedPort => string.IsNullOrEmpty(request.Headers["X-Forwarded-Port"]) ? (int?)null : int.Parse(request.Headers["X-Forwarded-Port"]); + public int? XForwardedPort + => string.IsNullOrEmpty(request.Headers["X-Forwarded-Port"]) ? (int?)null : int.Parse(request.Headers["X-Forwarded-Port"], CultureInfo.InvariantCulture); public string XForwardedProtocol => string.IsNullOrEmpty(request.Headers["X-Forwarded-Proto"]) ? null : request.Headers["X-Forwarded-Proto"]; From 2cb747651b134313ffdca930af38b07002a38992 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Wed, 13 Feb 2019 17:36:10 +0100 Subject: [PATCH 081/104] Correctly dispose WebSocketSharpListener --- .../SocketSharp/WebSocketSharpListener.cs | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs b/Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs index 4b6649217b..90bd981f5b 100644 --- a/Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs +++ b/Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs @@ -223,38 +223,39 @@ namespace Jellyfin.Server.SocketSharp public Task Stop() { _disposeCancellationTokenSource.Cancel(); - - if (_listener != null) - { - _listener.Close(); - } + _listener?.Close(); return Task.CompletedTask; } + /// + /// Releases the unmanaged resources and disposes of the managed resources used. + /// public void Dispose() { Dispose(true); + GC.SuppressFinalize(this); } private bool _disposed; - private readonly object _disposeLock = new object(); + + /// + /// Releases the unmanaged resources and disposes of the managed resources used. + /// + /// Whether or not the managed resources should be disposed protected virtual void Dispose(bool disposing) { - if (_disposed) return; - - lock (_disposeLock) + if (_disposed) { - if (_disposed) return; - - if (disposing) - { - Stop(); - } - - // release unmanaged resources here... - _disposed = true; + return; } + + if (disposing) + { + Stop().GetAwaiter().GetResult(); + } + + _disposed = true; } } } From 8b04fe76332e70ab579f0f9ac84012ef310e73cf Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Wed, 13 Feb 2019 18:37:44 +0100 Subject: [PATCH 082/104] More fixes --- Jellyfin.Server/SocketSharp/RequestMono.cs | 37 ++++++++++++------- Jellyfin.Server/SocketSharp/SharpWebSocket.cs | 27 +++++++++----- .../SocketSharp/WebSocketSharpListener.cs | 22 ++++++++--- .../SocketSharp/WebSocketSharpRequest.cs | 13 ++++++- 4 files changed, 70 insertions(+), 29 deletions(-) diff --git a/Jellyfin.Server/SocketSharp/RequestMono.cs b/Jellyfin.Server/SocketSharp/RequestMono.cs index 9a06017501..dd38b058b1 100644 --- a/Jellyfin.Server/SocketSharp/RequestMono.cs +++ b/Jellyfin.Server/SocketSharp/RequestMono.cs @@ -13,7 +13,7 @@ namespace Jellyfin.Server.SocketSharp { internal static string GetParameter(string header, string attr) { - int ap = header.IndexOf(attr); + int ap = header.IndexOf(attr, StringComparison.Ordinal); if (ap == -1) { return null; @@ -140,8 +140,12 @@ namespace Jellyfin.Server.SocketSharp v = v.Substring(0, 16) + "...\""; } - string msg = string.Format("A potentially dangerous Request.{0} value was " + - "detected from the client ({1}={2}).", name, key, v); + string msg = string.Format( + CultureInfo.InvariantCulture, + "A potentially dangerous Request.{0} value was detected from the client ({1}={2}).", + name, + key, + v); throw new Exception(msg); } @@ -258,6 +262,7 @@ namespace Jellyfin.Server.SocketSharp value.Append((char)c); } } + if (c == -1) { AddRawKeyValue(form, key, value); @@ -273,6 +278,7 @@ namespace Jellyfin.Server.SocketSharp key.Append((char)c); } } + if (c == -1) { AddRawKeyValue(form, key, value); @@ -310,6 +316,7 @@ namespace Jellyfin.Server.SocketSharp result.Append(key); result.Append('='); } + result.Append(pair.Value); } @@ -493,11 +500,6 @@ namespace Jellyfin.Server.SocketSharp public Stream InputStream => stream; } - private class Helpers - { - public static readonly CultureInfo InvariantCulture = CultureInfo.InvariantCulture; - } - internal static class StrUtils { public static bool StartsWith(string str1, string str2, bool ignore_case) @@ -535,12 +537,17 @@ namespace Jellyfin.Server.SocketSharp public class Element { - public string ContentType; - public string Name; - public string Filename; - public Encoding Encoding; - public long Start; - public long Length; + public string ContentType { get; set; } + + public string Name { get; set; } + + public string Filename { get; set; } + + public Encoding Encoding { get; set; } + + public long Start { get; set; } + + public long Length { get; set; } public override string ToString() { @@ -597,6 +604,7 @@ namespace Jellyfin.Server.SocketSharp { break; } + got_cr = b == CR; sb.Append((char)b); } @@ -797,6 +805,7 @@ namespace Jellyfin.Server.SocketSharp c = data.ReadByte(); continue; } + data.Position = retval + 2; if (got_cr) { diff --git a/Jellyfin.Server/SocketSharp/SharpWebSocket.cs b/Jellyfin.Server/SocketSharp/SharpWebSocket.cs index 5b233cdf5d..6eee4cd12e 100644 --- a/Jellyfin.Server/SocketSharp/SharpWebSocket.cs +++ b/Jellyfin.Server/SocketSharp/SharpWebSocket.cs @@ -24,6 +24,7 @@ namespace Jellyfin.Server.SocketSharp private TaskCompletionSource _taskCompletionSource = new TaskCompletionSource(); private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource(); + private bool _disposed = false; public SharpWebSocket(SocketHttpListener.WebSocket socket, ILogger logger) { @@ -40,9 +41,9 @@ namespace Jellyfin.Server.SocketSharp _logger = logger; WebSocket = socket; - socket.OnMessage += socket_OnMessage; - socket.OnClose += socket_OnClose; - socket.OnError += socket_OnError; + socket.OnMessage += OnSocketMessage; + socket.OnClose += OnSocketClose; + socket.OnError += OnSocketError; WebSocket.ConnectAsServer(); } @@ -52,21 +53,21 @@ namespace Jellyfin.Server.SocketSharp return _taskCompletionSource.Task; } - void socket_OnError(object sender, SocketHttpListener.ErrorEventArgs e) + private void OnSocketError(object sender, SocketHttpListener.ErrorEventArgs e) { _logger.LogError("Error in SharpWebSocket: {Message}", e.Message ?? string.Empty); // Closed?.Invoke(this, EventArgs.Empty); } - void socket_OnClose(object sender, SocketHttpListener.CloseEventArgs e) + private void OnSocketClose(object sender, SocketHttpListener.CloseEventArgs e) { _taskCompletionSource.TrySetResult(true); Closed?.Invoke(this, EventArgs.Empty); } - void socket_OnMessage(object sender, SocketHttpListener.MessageEventArgs e) + private void OnSocketMessage(object sender, SocketHttpListener.MessageEventArgs e) { if (OnReceiveBytes != null) { @@ -110,6 +111,7 @@ namespace Jellyfin.Server.SocketSharp public void Dispose() { Dispose(true); + GC.SuppressFinalize(this); } /// @@ -118,16 +120,23 @@ namespace Jellyfin.Server.SocketSharp /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool dispose) { + if (_disposed) + { + return; + } + if (dispose) { - WebSocket.OnMessage -= socket_OnMessage; - WebSocket.OnClose -= socket_OnClose; - WebSocket.OnError -= socket_OnError; + WebSocket.OnMessage -= OnSocketMessage; + WebSocket.OnClose -= OnSocketClose; + WebSocket.OnError -= OnSocketError; _cancellationTokenSource.Cancel(); WebSocket.Close(); } + + _disposed = true; } /// diff --git a/Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs b/Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs index 90bd981f5b..58c4d38a24 100644 --- a/Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs +++ b/Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs @@ -34,9 +34,16 @@ namespace Jellyfin.Server.SocketSharp private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource(); private CancellationToken _disposeCancellationToken; - public WebSocketSharpListener(ILogger logger, X509Certificate certificate, IStreamHelper streamHelper, - INetworkManager networkManager, ISocketFactory socketFactory, ICryptoProvider cryptoProvider, - bool enableDualMode, IFileSystem fileSystem, IEnvironmentInfo environment) + public WebSocketSharpListener( + ILogger logger, + X509Certificate certificate, + IStreamHelper streamHelper, + INetworkManager networkManager, + ISocketFactory socketFactory, + ICryptoProvider cryptoProvider, + bool enableDualMode, + IFileSystem fileSystem, + IEnvironmentInfo environment) { _logger = logger; _certificate = certificate; @@ -61,7 +68,9 @@ namespace Jellyfin.Server.SocketSharp public void Start(IEnumerable urlPrefixes) { if (_listener == null) + { _listener = new HttpListener(_logger, _cryptoProvider, _socketFactory, _networkManager, _streamHelper, _fileSystem, _environment); + } _listener.EnableDualMode = _enableDualMode; @@ -90,8 +99,11 @@ namespace Jellyfin.Server.SocketSharp { var url = request.Url.ToString(); - logger.LogInformation("{0} {1}. UserAgent: {2}", - request.IsWebSocketRequest ? "WS" : "HTTP " + request.HttpMethod, url, request.UserAgent ?? string.Empty); + logger.LogInformation( + "{0} {1}. UserAgent: {2}", + request.IsWebSocketRequest ? "WS" : "HTTP " + request.HttpMethod, + url, + request.UserAgent ?? string.Empty); } private Task InitTask(HttpListenerContext context, CancellationToken cancellationToken) diff --git a/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs b/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs index a19ea6bf7a..cbce7d4571 100644 --- a/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs +++ b/Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs @@ -42,7 +42,7 @@ namespace Jellyfin.Server.SocketSharp } var startHostUrl = listenerUrl.Substring(pos + "://".Length); - var endPos = startHostUrl.IndexOf('/'); + var endPos = startHostUrl.IndexOf('/', StringComparison.Ordinal); if (endPos == -1) { return null; @@ -110,6 +110,7 @@ namespace Jellyfin.Server.SocketSharp switch (crlf) { case 0: + { if (c == '\r') { crlf = 1; @@ -124,23 +125,31 @@ namespace Jellyfin.Server.SocketSharp { throw new ArgumentException("net_WebHeaderInvalidControlChars"); } + break; + } case 1: + { if (c == '\n') { crlf = 2; break; } + throw new ArgumentException("net_WebHeaderInvalidCRLFChars"); + } case 2: + { if (c == ' ' || c == '\t') { crlf = 0; break; } + throw new ArgumentException("net_WebHeaderInvalidCRLFChars"); + } } } @@ -349,6 +358,7 @@ namespace Jellyfin.Server.SocketSharp this.pathInfo = System.Net.WebUtility.UrlDecode(pathInfo); this.pathInfo = NormalizePathInfo(pathInfo, mode); } + return this.pathInfo; } } @@ -508,6 +518,7 @@ namespace Jellyfin.Server.SocketSharp i++; } } + return httpFiles; } } From e620bb95123f76c6eea92226a1e4c10d094ea65a Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Wed, 13 Feb 2019 18:47:26 +0100 Subject: [PATCH 083/104] Remove more doc warnings --- Jellyfin.Server/Jellyfin.Server.csproj | 2 +- jellyfin.ruleset | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index a6bf23f5be..1f2287a758 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -12,7 +12,7 @@ latest - SA1600 + SA1600;CS1591 diff --git a/jellyfin.ruleset b/jellyfin.ruleset index 25d11d7d35..4381349ca6 100644 --- a/jellyfin.ruleset +++ b/jellyfin.ruleset @@ -14,4 +14,8 @@ + + + + From cb9e50b2eae1cff7f21e893dee309a7ff629bd31 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Wed, 13 Feb 2019 18:55:23 +0100 Subject: [PATCH 084/104] Reorder elements --- Jellyfin.Server/SocketSharp/RequestMono.cs | 105 ++++++++++-------- .../SocketSharp/WebSocketSharpResponse.cs | 7 +- 2 files changed, 61 insertions(+), 51 deletions(-) diff --git a/Jellyfin.Server/SocketSharp/RequestMono.cs b/Jellyfin.Server/SocketSharp/RequestMono.cs index dd38b058b1..fe8e8242a6 100644 --- a/Jellyfin.Server/SocketSharp/RequestMono.cs +++ b/Jellyfin.Server/SocketSharp/RequestMono.cs @@ -185,6 +185,7 @@ namespace Jellyfin.Server.SocketSharp for (int idx = 1; idx < len; idx++) { char next = val[idx]; + // See http://secunia.com/advisories/14325 if (current == '<' || current == '\xff1c') { @@ -556,15 +557,23 @@ namespace Jellyfin.Server.SocketSharp } } - private Stream data; - private string boundary; - private byte[] boundary_bytes; - private byte[] buffer; - private bool at_eof; - private Encoding encoding; - private StringBuilder sb; + private const byte LF = (byte)'\n'; - private const byte LF = (byte)'\n', CR = (byte)'\r'; + private const byte CR = (byte)'\r'; + + private Stream data; + + private string boundary; + + private byte[] boundaryBytes; + + private byte[] buffer; + + private bool atEof; + + private Encoding encoding; + + private StringBuilder sb; // See RFC 2046 // In the case of multipart entities, in which one or more different @@ -580,12 +589,48 @@ namespace Jellyfin.Server.SocketSharp { this.data = data; boundary = b; - boundary_bytes = encoding.GetBytes(b); - buffer = new byte[boundary_bytes.Length + 2]; // CRLF or '--' + boundaryBytes = encoding.GetBytes(b); + buffer = new byte[boundaryBytes.Length + 2]; // CRLF or '--' this.encoding = encoding; sb = new StringBuilder(); } + public Element ReadNextElement() + { + if (atEof || ReadBoundary()) + { + return null; + } + + var elem = new Element(); + string header; + while ((header = ReadHeaders()) != null) + { + if (StrUtils.StartsWith(header, "Content-Disposition:", true)) + { + elem.Name = GetContentDispositionAttribute(header, "name"); + elem.Filename = StripPath(GetContentDispositionAttributeWithEncoding(header, "filename")); + } + else if (StrUtils.StartsWith(header, "Content-Type:", true)) + { + elem.ContentType = header.Substring("Content-Type:".Length).Trim(); + elem.Encoding = GetEncoding(elem.ContentType); + } + } + + long start = 0; + start = data.Position; + elem.Start = start; + long pos = MoveToNextBoundary(); + if (pos == -1) + { + return null; + } + + elem.Length = pos - start; + return elem; + } + private string ReadLine() { // CRLF or LF are ok as line endings. @@ -774,7 +819,7 @@ namespace Jellyfin.Server.SocketSharp return -1; } - if (!CompareBytes(boundary_bytes, buffer)) + if (!CompareBytes(boundaryBytes, buffer)) { state = 0; data.Position = retval + 2; @@ -790,7 +835,7 @@ namespace Jellyfin.Server.SocketSharp if (buffer[bl - 2] == '-' && buffer[bl - 1] == '-') { - at_eof = true; + atEof = true; } else if (buffer[bl - 2] != CR || buffer[bl - 1] != LF) { @@ -824,42 +869,6 @@ namespace Jellyfin.Server.SocketSharp return retval; } - public Element ReadNextElement() - { - if (at_eof || ReadBoundary()) - { - return null; - } - - var elem = new Element(); - string header; - while ((header = ReadHeaders()) != null) - { - if (StrUtils.StartsWith(header, "Content-Disposition:", true)) - { - elem.Name = GetContentDispositionAttribute(header, "name"); - elem.Filename = StripPath(GetContentDispositionAttributeWithEncoding(header, "filename")); - } - else if (StrUtils.StartsWith(header, "Content-Type:", true)) - { - elem.ContentType = header.Substring("Content-Type:".Length).Trim(); - elem.Encoding = GetEncoding(elem.ContentType); - } - } - - long start = 0; - start = data.Position; - elem.Start = start; - long pos = MoveToNextBoundary(); - if (pos == -1) - { - return null; - } - - elem.Length = pos - start; - return elem; - } - private static string StripPath(string path) { if (path == null || path.Length == 0) diff --git a/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs b/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs index 6de678b86c..56e5c73d61 100644 --- a/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs +++ b/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs @@ -18,6 +18,7 @@ namespace Jellyfin.Server.SocketSharp public class WebSocketSharpResponse : IHttpResponse { private readonly ILogger _logger; + private readonly HttpListenerResponse _response; public WebSocketSharpResponse(ILogger logger, HttpListenerResponse response, IRequest request) @@ -29,7 +30,9 @@ namespace Jellyfin.Server.SocketSharp } public IRequest Request { get; private set; } + public Dictionary Items { get; private set; } + public object OriginalResponse => _response; public int StatusCode @@ -50,7 +53,7 @@ namespace Jellyfin.Server.SocketSharp set => _response.ContentType = value; } - // public ICookies Cookies { get; set; } + public QueryParamCollection Headers => _response.Headers; public void AddHeader(string name, string value) { @@ -63,8 +66,6 @@ namespace Jellyfin.Server.SocketSharp _response.AddHeader(name, value); } - public QueryParamCollection Headers => _response.Headers; - public string GetHeader(string name) { return _response.Headers[name]; From 3947f2315dea8b7e390e219f188d0ecf3f5ee2d2 Mon Sep 17 00:00:00 2001 From: Vasily Date: Sat, 16 Feb 2019 00:05:47 +0100 Subject: [PATCH 085/104] Update Jellyfin.Server/Jellyfin.Server.csproj Co-Authored-By: Bond-009 --- Jellyfin.Server/Jellyfin.Server.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index 1f2287a758..bd670df527 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -11,7 +11,7 @@ latest - + SA1600;CS1591 From 18e1d03a89b7fe3ddba925f81b153d0f0cd1973c Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Sat, 16 Feb 2019 00:42:09 +0100 Subject: [PATCH 086/104] Comments --- Jellyfin.Server/SocketSharp/RequestMono.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Jellyfin.Server/SocketSharp/RequestMono.cs b/Jellyfin.Server/SocketSharp/RequestMono.cs index fe8e8242a6..24cf994eaf 100644 --- a/Jellyfin.Server/SocketSharp/RequestMono.cs +++ b/Jellyfin.Server/SocketSharp/RequestMono.cs @@ -445,7 +445,7 @@ namespace Jellyfin.Server.SocketSharp long virt = real - offset; if (virt < 0 || virt > Length) { - throw new ArgumentException("Invalid position", nameof(origin)); + throw new ArgumentException("Invalid position", nameof(d)); } position = s.Seek(real, SeekOrigin.Begin); @@ -618,8 +618,7 @@ namespace Jellyfin.Server.SocketSharp } } - long start = 0; - start = data.Position; + long start = data.Position; elem.Start = start; long pos = MoveToNextBoundary(); if (pos == -1) From f8ba55e2025c3ae7cfe6767629ec8382ae9c748a Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Fri, 15 Feb 2019 20:52:54 -0500 Subject: [PATCH 087/104] Update version to 10.2.0 release --- deployment/debian-package-x64/pkg-src/changelog | 6 ++++-- deployment/fedora-package-x64/pkg-src/jellyfin.spec | 10 ++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/deployment/debian-package-x64/pkg-src/changelog b/deployment/debian-package-x64/pkg-src/changelog index a4b55a4ec2..d0bdbd513d 100644 --- a/deployment/debian-package-x64/pkg-src/changelog +++ b/deployment/debian-package-x64/pkg-src/changelog @@ -1,4 +1,4 @@ -jellyfin (10.2.0~rc2) unstable; urgency=medium +jellyfin (10.2.0-1) unstable; urgency=medium * jellyfin: * PR452 Use EF Core for Activity database @@ -75,6 +75,8 @@ jellyfin (10.2.0~rc2) unstable; urgency=medium * PR869: Remove DLL support and require all packages/plugins to be zip archives * PR872: Fix potential NullReferenceException * PR890: Drop ETag and use Last-Modified header + * PR892: Add jellyfin-ffmpeg and versioning to package deps + * PR901: Properly dispose HttpWebResponse when the request failed to avoid 'too many open files' * jellyfin-web: * PR24 Add Master codeowners * PR34 Revert "Add Master codeowners" @@ -102,7 +104,7 @@ jellyfin (10.2.0~rc2) unstable; urgency=medium * PR127 Change sharedcomponents module to core * PR135 Make sure fallback culture is always available - -- Jellyfin Packaging Team Sun, 13 Feb 2019 01:03:20 -0500 + -- Jellyfin Packaging Team Fri, 15 Feb 2019 20:51:25 -0500 jellyfin (10.1.0-1) unstable; urgency=medium diff --git a/deployment/fedora-package-x64/pkg-src/jellyfin.spec b/deployment/fedora-package-x64/pkg-src/jellyfin.spec index 03fc0b6ff0..a017fcd8e3 100644 --- a/deployment/fedora-package-x64/pkg-src/jellyfin.spec +++ b/deployment/fedora-package-x64/pkg-src/jellyfin.spec @@ -8,7 +8,7 @@ Name: jellyfin Version: 10.2.0 -Release: rc2%{?dist} +Release: 1%{?dist} Summary: The Free Software Media Browser License: GPLv2 URL: https://jellyfin.media @@ -140,11 +140,10 @@ fi %systemd_postun_with_restart jellyfin.service %changelog -* Wed Feb 13 2019 Jellyfin Packaging Team +* Fri Feb 15 2019 Jellyfin Packaging Team - jellyfin: - PR452 Use EF Core for Activity database - PR535 Clean up streambuilder -- PR651 Release 10.1.0 - PR655 Support trying local branches in submodule - PR656 Do some logging in MediaInfoService - PR657 Remove conditions that are always true/false @@ -216,10 +215,9 @@ fi - PR869 Remove DLL support and require all packages/plugins to be zip archives - PR872 Fix potential NullReferenceException - PR890 Drop ETag and use Last-Modified header +- PR892: Add jellyfin-ffmpeg and versioning to package deps +- PR901: Properly dispose HttpWebResponse when the request failed to avoid 'too many open files' - jellyfin-web: -- PR24 Add Master codeowners -- PR34 Revert "Add Master codeowners" -- PR49 Release 10.1.0 - PR51 remove more code for sync and camera roll - PR56 Use English for fallback translations and clean up language files - PR58 Css slider fixes From 056e19f35027b30fcdbf09f560515940409a2357 Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Fri, 15 Feb 2019 21:04:12 -0500 Subject: [PATCH 088/104] Remove superfluous changelog entries --- deployment/debian-package-x64/pkg-src/changelog | 3 --- 1 file changed, 3 deletions(-) diff --git a/deployment/debian-package-x64/pkg-src/changelog b/deployment/debian-package-x64/pkg-src/changelog index d0bdbd513d..e3cbcc849b 100644 --- a/deployment/debian-package-x64/pkg-src/changelog +++ b/deployment/debian-package-x64/pkg-src/changelog @@ -78,9 +78,6 @@ jellyfin (10.2.0-1) unstable; urgency=medium * PR892: Add jellyfin-ffmpeg and versioning to package deps * PR901: Properly dispose HttpWebResponse when the request failed to avoid 'too many open files' * jellyfin-web: - * PR24 Add Master codeowners - * PR34 Revert "Add Master codeowners" - * PR49 Release 10.1.0 * PR51 remove more code for sync and camera roll * PR56 Use English for fallback translations and clean up language files * PR58 Css slider fixes From ff9a0c7e55573df45ea4d29d258149c0496abc51 Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Fri, 15 Feb 2019 21:04:20 -0500 Subject: [PATCH 089/104] Update submodule to 10.2.0 release --- MediaBrowser.WebDashboard/jellyfin-web | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.WebDashboard/jellyfin-web b/MediaBrowser.WebDashboard/jellyfin-web index 094c1deae9..f7e5946c79 160000 --- a/MediaBrowser.WebDashboard/jellyfin-web +++ b/MediaBrowser.WebDashboard/jellyfin-web @@ -1 +1 @@ -Subproject commit 094c1deae91c51b8bbf8ebb16a55758af110f04d +Subproject commit f7e5946c79728c6ac8956c9dd4305afa4190402c From c5ac36c88686e7384d31d870ba35f4bbe8c38fdb Mon Sep 17 00:00:00 2001 From: n8225 Date: Fri, 15 Feb 2019 23:34:16 -0600 Subject: [PATCH 090/104] Fix docker arm builds --- Dockerfile.arm | 15 +++++++++++---- Dockerfile.arm64 | 13 ++++++------- hooks/pre_build | 4 ++++ 3 files changed, 21 insertions(+), 11 deletions(-) create mode 100644 hooks/pre_build diff --git a/Dockerfile.arm b/Dockerfile.arm index 039274197c..0dc37a6446 100644 --- a/Dockerfile.arm +++ b/Dockerfile.arm @@ -1,23 +1,30 @@ +# Requires binfm_misc registration for arm +# https://github.com/multiarch/qemu-user-static#binfmt_misc-register ARG DOTNET_VERSION=3.0 -FROM microsoft/dotnet:${DOTNET_VERSION}-sdk-stretch-arm32v7 as builder +FROM multiarch/qemu-user-static:x86_64-arm as qemu +FROM alpine as qemu_extract +COPY --from=qemu /usr/bin qemu-arm-static.tar.gz +RUN tar -xzvf qemu-arm-static.tar.gz + +FROM microsoft/dotnet:${DOTNET_VERSION}-sdk-stretch as builder WORKDIR /repo COPY . . #TODO Remove or update the sed line when we update dotnet version. RUN export DOTNET_CLI_TELEMETRY_OPTOUT=1 \ && find . -type f -exec sed -i 's/netcoreapp2.1/netcoreapp3.0/g' {} \; \ - && dotnet clean -maxcpucount:1 \ && dotnet publish \ - -maxcpucount:1 \ + -r linux-arm \ --configuration release \ --output /jellyfin \ Jellyfin.Server FROM microsoft/dotnet:${DOTNET_VERSION}-runtime-stretch-slim-arm32v7 +COPY --from=qemu_extract qemu-arm-static /usr/bin RUN apt-get update \ - && apt-get install -y ffmpeg + && apt-get install --no-install-recommends --no-install-suggests -y ffmpeg COPY --from=builder /jellyfin /jellyfin EXPOSE 8096 VOLUME /config /media diff --git a/Dockerfile.arm64 b/Dockerfile.arm64 index 06ba21b918..ec42610c00 100644 --- a/Dockerfile.arm64 +++ b/Dockerfile.arm64 @@ -5,28 +5,27 @@ ARG DOTNET_VERSION=3.0 FROM multiarch/qemu-user-static:x86_64-aarch64 as qemu FROM alpine as qemu_extract -COPY --from=qemu /usr/bin qemu_user_static.tgz -RUN tar -xzvf qemu_user_static.tgz +COPY --from=qemu /usr/bin qemu-aarch64-static.tar.gz +RUN tar -xzvf qemu-aarch64-static.tar.gz -FROM microsoft/dotnet:${DOTNET_VERSION}-sdk-stretch-arm64v8 as builder -COPY --from=qemu_extract qemu-* /usr/bin +FROM microsoft/dotnet:${DOTNET_VERSION}-sdk-stretch as builder WORKDIR /repo COPY . . #TODO Remove or update the sed line when we update dotnet version. RUN export DOTNET_CLI_TELEMETRY_OPTOUT=1 \ && find . -type f -exec sed -i 's/netcoreapp2.1/netcoreapp3.0/g' {} \; \ - && dotnet clean \ && dotnet publish \ + -r linux-arm64 \ --configuration release \ --output /jellyfin \ Jellyfin.Server FROM microsoft/dotnet:${DOTNET_VERSION}-runtime-stretch-slim-arm64v8 +COPY --from=qemu_extract qemu-aarch64-static /usr/bin RUN apt-get update \ - && apt-get install -y ffmpeg -COPY --from=qemu_extract qemu-* /usr/bin + && apt-get install --no-install-recommends --no-install-suggests -y ffmpeg COPY --from=builder /jellyfin /jellyfin EXPOSE 8096 VOLUME /config /media diff --git a/hooks/pre_build b/hooks/pre_build new file mode 100644 index 0000000000..a08c740b38 --- /dev/null +++ b/hooks/pre_build @@ -0,0 +1,4 @@ +#!/bin/bash +# Register qemu-*-static for all supported processors except the +# current one, but also remove all registered binfmt_misc before +docker run --rm --privileged multiarch/qemu-user-static:register --reset From d9ab654abe6a6790ecb946894dac0c4fc863227b Mon Sep 17 00:00:00 2001 From: Andrew Rabert Date: Sat, 16 Feb 2019 01:37:55 -0500 Subject: [PATCH 091/104] Enhance Dockerfiles * Prevent failure when obj exists from host compile * Enhance readability of disposed stages * Formatting --- Dockerfile | 5 ++--- Dockerfile.arm | 21 ++++++++++++--------- Dockerfile.arm64 | 13 ++++++++----- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/Dockerfile b/Dockerfile index 266b59f1c8..67505a57d9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,9 +3,8 @@ ARG DOTNET_VERSION=2 FROM microsoft/dotnet:${DOTNET_VERSION}-sdk as builder WORKDIR /repo COPY . . -RUN export DOTNET_CLI_TELEMETRY_OPTOUT=1 \ - && dotnet clean \ - && dotnet publish \ +ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 +RUN dotnet publish \ --configuration release \ --output /jellyfin \ Jellyfin.Server diff --git a/Dockerfile.arm b/Dockerfile.arm index 0dc37a6446..802f45ff24 100644 --- a/Dockerfile.arm +++ b/Dockerfile.arm @@ -1,20 +1,23 @@ -# Requires binfm_misc registration for arm -# https://github.com/multiarch/qemu-user-static#binfmt_misc-register +# Requires binfm_misc registration +# https://github.com/multiarch/qemu-user-static#binfmt_misc-register ARG DOTNET_VERSION=3.0 -FROM multiarch/qemu-user-static:x86_64-arm as qemu -FROM alpine as qemu_extract -COPY --from=qemu /usr/bin qemu-arm-static.tar.gz +FROM multiarch/qemu-user-static:x86_64-arm as qemu +FROM alpine as qemu_extract +COPY --from=qemu /usr/bin qemu-arm-static.tar.gz RUN tar -xzvf qemu-arm-static.tar.gz FROM microsoft/dotnet:${DOTNET_VERSION}-sdk-stretch as builder WORKDIR /repo COPY . . -#TODO Remove or update the sed line when we update dotnet version. -RUN export DOTNET_CLI_TELEMETRY_OPTOUT=1 \ - && find . -type f -exec sed -i 's/netcoreapp2.1/netcoreapp3.0/g' {} \; \ - && dotnet publish \ +ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 +# TODO Remove or update the sed line when we update dotnet version. +RUN find . -type f -exec sed -i 's/netcoreapp2.1/netcoreapp3.0/g' {} \; +# Discard objs - may cause failures if exists +RUN find . -type d -name obj | xargs -r rm -r +# Build +RUN dotnet publish \ -r linux-arm \ --configuration release \ --output /jellyfin \ diff --git a/Dockerfile.arm64 b/Dockerfile.arm64 index ec42610c00..3175c950c6 100644 --- a/Dockerfile.arm64 +++ b/Dockerfile.arm64 @@ -1,4 +1,4 @@ -# Requires binfm_misc registration for aarch64 +# Requires binfm_misc registration # https://github.com/multiarch/qemu-user-static#binfmt_misc-register ARG DOTNET_VERSION=3.0 @@ -12,10 +12,13 @@ RUN tar -xzvf qemu-aarch64-static.tar.gz FROM microsoft/dotnet:${DOTNET_VERSION}-sdk-stretch as builder WORKDIR /repo COPY . . -#TODO Remove or update the sed line when we update dotnet version. -RUN export DOTNET_CLI_TELEMETRY_OPTOUT=1 \ - && find . -type f -exec sed -i 's/netcoreapp2.1/netcoreapp3.0/g' {} \; \ - && dotnet publish \ +ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 +# TODO Remove or update the sed line when we update dotnet version. +RUN find . -type f -exec sed -i 's/netcoreapp2.1/netcoreapp3.0/g' {} \; +# Discard objs - may cause failures if exists +RUN find . -type d -name obj | xargs -r rm -r +# Build +RUN dotnet publish \ -r linux-arm64 \ --configuration release \ --output /jellyfin \ From 26e2ffdd31f7425f37060c9e5f07a7e6815fbe94 Mon Sep 17 00:00:00 2001 From: Andrew Rabert Date: Sat, 16 Feb 2019 01:45:48 -0500 Subject: [PATCH 092/104] Checkout submodules in Docker Hub hook --- hooks/pre_build | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hooks/pre_build b/hooks/pre_build index a08c740b38..2fd6136c53 100644 --- a/hooks/pre_build +++ b/hooks/pre_build @@ -1,4 +1,6 @@ #!/bin/bash +git submodule update --init --recursive + # Register qemu-*-static for all supported processors except the # current one, but also remove all registered binfmt_misc before docker run --rm --privileged multiarch/qemu-user-static:register --reset From a9934206761251a58d95c590bb87c9b0177e6754 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Sat, 16 Feb 2019 11:41:48 +0100 Subject: [PATCH 093/104] Reduce log spam --- Emby.Server.Implementations/ApplicationHost.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 784486d524..2490b97175 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -471,7 +471,7 @@ namespace Emby.Server.Implementations { try { - Logger.LogWarning("Creating instance of {Type}", type); + Logger.LogDebug("Creating instance of {Type}", type); return ActivatorUtilities.CreateInstance(_serviceProvider, type); } catch (Exception ex) From a15098dc0007c54ac30cf851043c9102b9c82104 Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Sat, 16 Feb 2019 12:13:38 -0500 Subject: [PATCH 094/104] Bump release version for last-minute PRs --- deployment/debian-package-x64/pkg-src/changelog | 7 +++++-- deployment/fedora-package-x64/pkg-src/jellyfin.spec | 6 +++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/deployment/debian-package-x64/pkg-src/changelog b/deployment/debian-package-x64/pkg-src/changelog index e3cbcc849b..869dc4a5e2 100644 --- a/deployment/debian-package-x64/pkg-src/changelog +++ b/deployment/debian-package-x64/pkg-src/changelog @@ -1,9 +1,8 @@ -jellyfin (10.2.0-1) unstable; urgency=medium +jellyfin (10.2.0-2) unstable; urgency=medium * jellyfin: * PR452 Use EF Core for Activity database * PR535 Clean up streambuilder - * PR651 Release 10.1.0 * PR655 Support trying local branches in submodule * PR656 Do some logging in MediaInfoService * PR657 Remove conditions that are always true/false @@ -76,7 +75,11 @@ jellyfin (10.2.0-1) unstable; urgency=medium * PR872: Fix potential NullReferenceException * PR890: Drop ETag and use Last-Modified header * PR892: Add jellyfin-ffmpeg and versioning to package deps + * PR899: DLNA: Fix race condition leading to missing device names * PR901: Properly dispose HttpWebResponse when the request failed to avoid 'too many open files' + * PR909: Fix docker arm builds + * PR910: Enhance Dockerfiles + * PR911: Checkout submodules in Docker Hub hook * jellyfin-web: * PR51 remove more code for sync and camera roll * PR56 Use English for fallback translations and clean up language files diff --git a/deployment/fedora-package-x64/pkg-src/jellyfin.spec b/deployment/fedora-package-x64/pkg-src/jellyfin.spec index a017fcd8e3..75821cb171 100644 --- a/deployment/fedora-package-x64/pkg-src/jellyfin.spec +++ b/deployment/fedora-package-x64/pkg-src/jellyfin.spec @@ -8,7 +8,7 @@ Name: jellyfin Version: 10.2.0 -Release: 1%{?dist} +Release: 2%{?dist} Summary: The Free Software Media Browser License: GPLv2 URL: https://jellyfin.media @@ -214,9 +214,13 @@ fi - PR868 Fix audio streaming via BaseProgressiveStreamingService - PR869 Remove DLL support and require all packages/plugins to be zip archives - PR872 Fix potential NullReferenceException +- PR899: DLNA: Fix race condition leading to missing device names - PR890 Drop ETag and use Last-Modified header - PR892: Add jellyfin-ffmpeg and versioning to package deps - PR901: Properly dispose HttpWebResponse when the request failed to avoid 'too many open files' +- PR909: Fix docker arm builds +- PR910: Enhance Dockerfiles +- PR911: Checkout submodules in Docker Hub hook - jellyfin-web: - PR51 remove more code for sync and camera roll - PR56 Use English for fallback translations and clean up language files From c06598635f2637dc60e022825e7a81bdae88a650 Mon Sep 17 00:00:00 2001 From: Andrew Rabert Date: Sat, 16 Feb 2019 15:25:44 -0500 Subject: [PATCH 095/104] Fix cachedir missing from Docker container Adds the /cache volume and set it to writeable by all. This allows for those using jellyfin to continue using it without modifying their config. However, retaining cache will require one to mount the /cache volume. Also make the /config and /media dirs 777 by default. No permissions on mounted volumes will be changed. --- Dockerfile | 8 +++++--- Dockerfile.arm | 8 +++++--- Dockerfile.arm64 | 8 +++++--- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/Dockerfile b/Dockerfile index 67505a57d9..6c0d2515f4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,9 +17,11 @@ RUN apt-get update \ libfontconfig1 \ && apt-get clean autoclean \ && apt-get autoremove \ - && rm -rf /var/lib/{apt,dpkg,cache,log} + && rm -rf /var/lib/{apt,dpkg,cache,log} \ + && mkdir -p /cache /config /media \ + && chmod 777 /cache /config /media COPY --from=ffmpeg / / COPY --from=builder /jellyfin /jellyfin EXPOSE 8096 -VOLUME /config /media -ENTRYPOINT dotnet /jellyfin/jellyfin.dll --datadir /config +VOLUME /cache /config /media +ENTRYPOINT dotnet /jellyfin/jellyfin.dll --datadir /config --cachedir /cache diff --git a/Dockerfile.arm b/Dockerfile.arm index 802f45ff24..9d1c30619b 100644 --- a/Dockerfile.arm +++ b/Dockerfile.arm @@ -27,8 +27,10 @@ RUN dotnet publish \ FROM microsoft/dotnet:${DOTNET_VERSION}-runtime-stretch-slim-arm32v7 COPY --from=qemu_extract qemu-arm-static /usr/bin RUN apt-get update \ - && apt-get install --no-install-recommends --no-install-suggests -y ffmpeg + && apt-get install --no-install-recommends --no-install-suggests -y ffmpeg \ + && mkdir -p /cache /config /media \ + && chmod 777 /cache /config /media COPY --from=builder /jellyfin /jellyfin EXPOSE 8096 -VOLUME /config /media -ENTRYPOINT dotnet /jellyfin/jellyfin.dll --datadir /config +VOLUME /cache /config /media +ENTRYPOINT dotnet /jellyfin/jellyfin.dll --datadir /config --cachedir /cache diff --git a/Dockerfile.arm64 b/Dockerfile.arm64 index 3175c950c6..e61aaa167c 100644 --- a/Dockerfile.arm64 +++ b/Dockerfile.arm64 @@ -28,8 +28,10 @@ RUN dotnet publish \ FROM microsoft/dotnet:${DOTNET_VERSION}-runtime-stretch-slim-arm64v8 COPY --from=qemu_extract qemu-aarch64-static /usr/bin RUN apt-get update \ - && apt-get install --no-install-recommends --no-install-suggests -y ffmpeg + && apt-get install --no-install-recommends --no-install-suggests -y ffmpeg \ + && mkdir -p /cache /config /media \ + && chmod 777 /cache /config /media COPY --from=builder /jellyfin /jellyfin EXPOSE 8096 -VOLUME /config /media -ENTRYPOINT dotnet /jellyfin/jellyfin.dll --datadir /config +VOLUME /cache /config /media +ENTRYPOINT dotnet /jellyfin/jellyfin.dll --datadir /config --cachedir /cache From 0d5fbcb031d551d3ee858b3d047fcc6f5ad61a06 Mon Sep 17 00:00:00 2001 From: William Taylor Date: Fri, 8 Feb 2019 09:13:58 +0000 Subject: [PATCH 096/104] Removed primitives from services in Program.cs This will make it easier to move dependency registration to a system without having to new up all the services first. Moved the primitives to an IConfiguration which is much easier to inject. --- .../ConfigurationOptions.cs | 14 +++++ .../Emby.Server.Implementations.csproj | 6 +++ .../IO/ManagedFileSystem.cs | 28 +++++----- Jellyfin.Server/Program.cs | 53 +++++++++++-------- 4 files changed, 66 insertions(+), 35 deletions(-) create mode 100644 Emby.Server.Implementations/ConfigurationOptions.cs diff --git a/Emby.Server.Implementations/ConfigurationOptions.cs b/Emby.Server.Implementations/ConfigurationOptions.cs new file mode 100644 index 0000000000..0483ad207f --- /dev/null +++ b/Emby.Server.Implementations/ConfigurationOptions.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using Emby.Server.Implementations.IO; + +namespace Emby.Server.Implementations +{ + public static class ConfigurationOptions + { + public static readonly Dictionary Configuration = new Dictionary + { + {"ManagedFileSystem:DefaultDirectory", null}, + {"ManagedFileSystem:EnableSeparateFileAndDirectoryQueries", "True"} + }; + } +} diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 6bf776f533..16258c767c 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -46,4 +46,10 @@ + + + ..\..\..\.nuget\packages\microsoft.extensions.configuration.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.Abstractions.dll + + + diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 7c44878ec2..8ffb0f74a9 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -4,8 +4,10 @@ using System.Diagnostics; using System.IO; using System.Linq; using System.Text; +using MediaBrowser.Common.Configuration; using MediaBrowser.Model.IO; using MediaBrowser.Model.System; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.IO @@ -20,30 +22,30 @@ namespace Emby.Server.Implementations.IO private readonly bool _supportsAsyncFileStreams; private char[] _invalidFileNameChars; private readonly List _shortcutHandlers = new List(); - private bool EnableSeparateFileAndDirectoryQueries; + private readonly bool EnableSeparateFileAndDirectoryQueries; - private string _tempPath; + private readonly string _tempPath; - private IEnvironmentInfo _environmentInfo; - private bool _isEnvironmentCaseInsensitive; + private readonly IEnvironmentInfo _environmentInfo; + private readonly bool _isEnvironmentCaseInsensitive; - private string _defaultDirectory; + private readonly string _defaultDirectory; public ManagedFileSystem( ILoggerFactory loggerFactory, IEnvironmentInfo environmentInfo, - string defaultDirectory, - string tempPath, - bool enableSeparateFileAndDirectoryQueries) + IApplicationPaths applicationPaths, + IConfiguration configuration) { Logger = loggerFactory.CreateLogger("FileSystem"); _supportsAsyncFileStreams = true; - _tempPath = tempPath; + _tempPath = applicationPaths.TempDirectory; _environmentInfo = environmentInfo; - _defaultDirectory = defaultDirectory; + _defaultDirectory = configuration["ManagedFileSystem:DefaultDirectory"]; // On Linux with mono, this needs to be true or symbolic links are ignored - EnableSeparateFileAndDirectoryQueries = enableSeparateFileAndDirectoryQueries; + EnableSeparateFileAndDirectoryQueries = + bool.Parse(configuration["ManagedFileSystem:EnableSeparateFileAndDirectoryQueries"]); SetInvalidFileNameChars(environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows); @@ -718,7 +720,7 @@ namespace Emby.Server.Implementations.IO SetAttributes(path, false, false); File.Delete(path); } - + public virtual List GetDrives() { // Only include drives in the ready state or this method could end up being very slow, waiting for drives to timeout @@ -790,7 +792,7 @@ namespace Emby.Server.Implementations.IO { return infos.Select(GetFileSystemMetadata); } - + public virtual IEnumerable GetDirectoryPaths(string path, bool recursive = false) { var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index ac5aab4609..7236238c2f 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -35,6 +35,7 @@ namespace Jellyfin.Server private static readonly ILoggerFactory _loggerFactory = new SerilogLoggerFactory(); private static ILogger _logger; private static bool _restartOnShutdown; + private static IConfiguration appConfig; public static async Task Main(string[] args) { @@ -78,7 +79,11 @@ namespace Jellyfin.Server // $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", appPaths.LogDirectoryPath); - await CreateLogger(appPaths).ConfigureAwait(false); + + appConfig = await CreateConfiguration(appPaths).ConfigureAwait(false); + + await CreateLogger(appConfig, appPaths).ConfigureAwait(false); + _logger = _loggerFactory.CreateLogger("Main"); AppDomain.CurrentDomain.UnhandledException += (sender, e) @@ -121,7 +126,7 @@ namespace Jellyfin.Server // Allow all https requests ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; } ); - var fileSystem = new ManagedFileSystem(_loggerFactory, environmentInfo, null, appPaths.TempDirectory, true); + var fileSystem = new ManagedFileSystem(_loggerFactory, environmentInfo, appPaths, appConfig); using (var appHost = new CoreAppHost( appPaths, @@ -309,29 +314,33 @@ namespace Jellyfin.Server return new ServerApplicationPaths(dataDir, logDir, configDir, cacheDir); } - private static async Task CreateLogger(IApplicationPaths appPaths) + private static async Task CreateConfiguration(IApplicationPaths appPaths) + { + string configPath = Path.Combine(appPaths.ConfigurationDirectoryPath, "logging.json"); + + if (!File.Exists(configPath)) + { + // For some reason the csproj name is used instead of the assembly name + using (Stream rscstr = typeof(Program).Assembly + .GetManifestResourceStream("Jellyfin.Server.Resources.Configuration.logging.json")) + using (Stream fstr = File.Open(configPath, FileMode.CreateNew)) + { + await rscstr.CopyToAsync(fstr).ConfigureAwait(false); + } + } + + return new ConfigurationBuilder() + .SetBasePath(appPaths.ConfigurationDirectoryPath) + .AddJsonFile("logging.json") + .AddEnvironmentVariables("JELLYFIN_") + .AddInMemoryCollection(ConfigurationOptions.Configuration) + .Build(); + } + + private static async Task CreateLogger(IConfiguration configuration, IApplicationPaths appPaths) { try { - string configPath = Path.Combine(appPaths.ConfigurationDirectoryPath, "logging.json"); - - if (!File.Exists(configPath)) - { - // For some reason the csproj name is used instead of the assembly name - using (Stream rscstr = typeof(Program).Assembly - .GetManifestResourceStream("Jellyfin.Server.Resources.Configuration.logging.json")) - using (Stream fstr = File.Open(configPath, FileMode.CreateNew)) - { - await rscstr.CopyToAsync(fstr).ConfigureAwait(false); - } - } - - var configuration = new ConfigurationBuilder() - .SetBasePath(appPaths.ConfigurationDirectoryPath) - .AddJsonFile("logging.json") - .AddEnvironmentVariables("JELLYFIN_") - .Build(); - // Serilog.Log is used by SerilogLoggerFactory when no logger is specified Serilog.Log.Logger = new LoggerConfiguration() .ReadFrom.Configuration(configuration) From 72aa364aa5578c0a6e2ee8219ca7ee1675a7e50e Mon Sep 17 00:00:00 2001 From: William Taylor Date: Wed, 13 Feb 2019 17:50:40 +0000 Subject: [PATCH 097/104] Removed extra using --- Emby.Server.Implementations/ConfigurationOptions.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Emby.Server.Implementations/ConfigurationOptions.cs b/Emby.Server.Implementations/ConfigurationOptions.cs index 0483ad207f..b9b95d65d5 100644 --- a/Emby.Server.Implementations/ConfigurationOptions.cs +++ b/Emby.Server.Implementations/ConfigurationOptions.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using Emby.Server.Implementations.IO; namespace Emby.Server.Implementations { From 3f80b16ffaabfb7625fefd1faad7e704c66171b7 Mon Sep 17 00:00:00 2001 From: William Taylor Date: Thu, 14 Feb 2019 17:59:22 +0000 Subject: [PATCH 098/104] Removed Reference and replaced with package reference --- .../Emby.Server.Implementations.csproj | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 16258c767c..bbf165d627 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -24,6 +24,7 @@ + @@ -46,10 +47,4 @@ - - - ..\..\..\.nuget\packages\microsoft.extensions.configuration.abstractions\2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.Abstractions.dll - - - From 18ae107ce46cf90c4a58f578b928216e0a34e597 Mon Sep 17 00:00:00 2001 From: William Taylor Date: Sun, 17 Feb 2019 10:54:47 +0000 Subject: [PATCH 099/104] Removed unnecessary configuration options and reduced primitive dependencies --- .../ApplicationHost.cs | 18 ++++---- .../ConfigurationOptions.cs | 3 +- .../HttpServer/HttpListenerHost.cs | 12 ++--- .../IO/ManagedFileSystem.cs | 45 ++----------------- Jellyfin.Server/CoreAppHost.cs | 21 ++++++++- Jellyfin.Server/Program.cs | 5 ++- MediaBrowser.Api/EnvironmentService.cs | 10 +---- MediaBrowser.Model/IO/IFileSystem.cs | 2 - 8 files changed, 43 insertions(+), 73 deletions(-) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 784486d524..44c74ad5de 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -104,10 +104,10 @@ using MediaBrowser.Providers.Manager; using MediaBrowser.Providers.Subtitles; using MediaBrowser.WebDashboard.Api; using MediaBrowser.XbmcMetadata.Providers; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using Microsoft.Extensions.DependencyInjection; using ServiceStack; -using ServiceStack.Text.Jsv; using X509Certificate = System.Security.Cryptography.X509Certificates.X509Certificate; namespace Emby.Server.Implementations @@ -318,6 +318,8 @@ namespace Emby.Server.Implementations private IMediaSourceManager MediaSourceManager { get; set; } private IPlaylistManager PlaylistManager { get; set; } + private readonly IConfiguration _configuration; + /// /// Gets or sets the installation manager. /// @@ -356,8 +358,10 @@ namespace Emby.Server.Implementations IFileSystem fileSystem, IEnvironmentInfo environmentInfo, IImageEncoder imageEncoder, - INetworkManager networkManager) + INetworkManager networkManager, + IConfiguration configuration) { + _configuration = configuration; // hack alert, until common can target .net core BaseExtensions.CryptographyProvider = CryptographyProvider; @@ -727,11 +731,10 @@ namespace Emby.Server.Implementations HttpServer = new HttpListenerHost(this, LoggerFactory, ServerConfigurationManager, - "web/index.html", + _configuration, NetworkManager, JsonSerializer, - XmlSerializer, - GetParseFn); + XmlSerializer); HttpServer.GlobalResponse = LocalizationManager.GetLocalizedString("StartupEmbyServerIsLoading"); serviceCollection.AddSingleton(HttpServer); @@ -831,11 +834,6 @@ namespace Emby.Server.Implementations return null; } - private static Func GetParseFn(Type propertyType) - { - return s => JsvReader.GetParseFn(propertyType)(s); - } - public virtual string PackageRuntime => "netcore"; public static void LogEnvironmentInfo(ILogger logger, IApplicationPaths appPaths, EnvironmentInfo.EnvironmentInfo environmentInfo) diff --git a/Emby.Server.Implementations/ConfigurationOptions.cs b/Emby.Server.Implementations/ConfigurationOptions.cs index b9b95d65d5..30bfd87498 100644 --- a/Emby.Server.Implementations/ConfigurationOptions.cs +++ b/Emby.Server.Implementations/ConfigurationOptions.cs @@ -6,8 +6,7 @@ namespace Emby.Server.Implementations { public static readonly Dictionary Configuration = new Dictionary { - {"ManagedFileSystem:DefaultDirectory", null}, - {"ManagedFileSystem:EnableSeparateFileAndDirectoryQueries", "True"} + {"HttpListenerHost:DefaultRedirectPath", "web/index.html"} }; } } diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs index 834ffb1304..d78891ac7c 100644 --- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs +++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs @@ -19,7 +19,9 @@ using MediaBrowser.Model.Events; using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Services; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; +using ServiceStack.Text.Jsv; namespace Emby.Server.Implementations.HttpServer { @@ -53,20 +55,20 @@ namespace Emby.Server.Implementations.HttpServer IServerApplicationHost applicationHost, ILoggerFactory loggerFactory, IServerConfigurationManager config, - string defaultRedirectPath, + IConfiguration configuration, INetworkManager networkManager, IJsonSerializer jsonSerializer, - IXmlSerializer xmlSerializer, - Func> funcParseFn) + IXmlSerializer xmlSerializer) { _appHost = applicationHost; _logger = loggerFactory.CreateLogger("HttpServer"); _config = config; - DefaultRedirectPath = defaultRedirectPath; + DefaultRedirectPath = configuration["HttpListenerHost:DefaultRedirectPath"]; _networkManager = networkManager; _jsonSerializer = jsonSerializer; _xmlSerializer = xmlSerializer; - _funcParseFn = funcParseFn; + + _funcParseFn = t => s => JsvReader.GetParseFn(t)(s); Instance = this; ResponseFilters = Array.Empty>(); diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 8ffb0f74a9..a64dfb607b 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -22,61 +22,27 @@ namespace Emby.Server.Implementations.IO private readonly bool _supportsAsyncFileStreams; private char[] _invalidFileNameChars; private readonly List _shortcutHandlers = new List(); - private readonly bool EnableSeparateFileAndDirectoryQueries; private readonly string _tempPath; private readonly IEnvironmentInfo _environmentInfo; private readonly bool _isEnvironmentCaseInsensitive; - private readonly string _defaultDirectory; - public ManagedFileSystem( ILoggerFactory loggerFactory, IEnvironmentInfo environmentInfo, - IApplicationPaths applicationPaths, - IConfiguration configuration) + IApplicationPaths applicationPaths) { Logger = loggerFactory.CreateLogger("FileSystem"); _supportsAsyncFileStreams = true; _tempPath = applicationPaths.TempDirectory; _environmentInfo = environmentInfo; - _defaultDirectory = configuration["ManagedFileSystem:DefaultDirectory"]; - - // On Linux with mono, this needs to be true or symbolic links are ignored - EnableSeparateFileAndDirectoryQueries = - bool.Parse(configuration["ManagedFileSystem:EnableSeparateFileAndDirectoryQueries"]); SetInvalidFileNameChars(environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows); _isEnvironmentCaseInsensitive = environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows; } - public virtual string DefaultDirectory - { - get - { - var value = _defaultDirectory; - - if (!string.IsNullOrEmpty(value)) - { - try - { - if (Directory.Exists(value)) - { - return value; - } - } - catch - { - - } - } - - return null; - } - } - public virtual void AddShortcutHandler(IShortcutHandler handler) { _shortcutHandlers.Add(handler); @@ -779,13 +745,8 @@ namespace Emby.Server.Implementations.IO var directoryInfo = new DirectoryInfo(path); var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; - if (EnableSeparateFileAndDirectoryQueries) - { - return ToMetadata(directoryInfo.EnumerateDirectories("*", searchOption)) - .Concat(ToMetadata(directoryInfo.EnumerateFiles("*", searchOption))); - } - - return ToMetadata(directoryInfo.EnumerateFileSystemInfos("*", searchOption)); + return ToMetadata(directoryInfo.EnumerateDirectories("*", searchOption)) + .Concat(ToMetadata(directoryInfo.EnumerateFiles("*", searchOption))); } private IEnumerable ToMetadata(IEnumerable infos) diff --git a/Jellyfin.Server/CoreAppHost.cs b/Jellyfin.Server/CoreAppHost.cs index 126cb467f9..84d78d3fb6 100644 --- a/Jellyfin.Server/CoreAppHost.cs +++ b/Jellyfin.Server/CoreAppHost.cs @@ -5,14 +5,31 @@ using Emby.Server.Implementations.HttpServer; using Jellyfin.Server.SocketSharp; using MediaBrowser.Model.IO; using MediaBrowser.Model.System; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; namespace Jellyfin.Server { public class CoreAppHost : ApplicationHost { - public CoreAppHost(ServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, StartupOptions options, IFileSystem fileSystem, IEnvironmentInfo environmentInfo, MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, MediaBrowser.Common.Net.INetworkManager networkManager) - : base(applicationPaths, loggerFactory, options, fileSystem, environmentInfo, imageEncoder, networkManager) + public CoreAppHost( + ServerApplicationPaths applicationPaths, + ILoggerFactory loggerFactory, + StartupOptions options, + IFileSystem fileSystem, + IEnvironmentInfo environmentInfo, + MediaBrowser.Controller.Drawing.IImageEncoder imageEncoder, + MediaBrowser.Common.Net.INetworkManager networkManager, + IConfiguration configuration) + : base( + applicationPaths, + loggerFactory, + options, + fileSystem, + environmentInfo, + imageEncoder, + networkManager, + configuration) { } diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 7236238c2f..b822815542 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -126,7 +126,7 @@ namespace Jellyfin.Server // Allow all https requests ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; } ); - var fileSystem = new ManagedFileSystem(_loggerFactory, environmentInfo, appPaths, appConfig); + var fileSystem = new ManagedFileSystem(_loggerFactory, environmentInfo, appPaths); using (var appHost = new CoreAppHost( appPaths, @@ -135,7 +135,8 @@ namespace Jellyfin.Server fileSystem, environmentInfo, new NullImageEncoder(), - new NetworkManager(_loggerFactory, environmentInfo))) + new NetworkManager(_loggerFactory, environmentInfo), + appConfig)) { await appHost.Init(new ServiceCollection()).ConfigureAwait(false); diff --git a/MediaBrowser.Api/EnvironmentService.cs b/MediaBrowser.Api/EnvironmentService.cs index bdd7a8f8f9..f4813e7132 100644 --- a/MediaBrowser.Api/EnvironmentService.cs +++ b/MediaBrowser.Api/EnvironmentService.cs @@ -173,14 +173,8 @@ namespace MediaBrowser.Api _fileSystem.DeleteFile(file); } - public object Get(GetDefaultDirectoryBrowser request) - { - var result = new DefaultDirectoryBrowserInfo(); - - result.Path = _fileSystem.DefaultDirectory; - - return ToOptimizedResult(result); - } + public object Get(GetDefaultDirectoryBrowser request) => + ToOptimizedResult(new DefaultDirectoryBrowserInfo {Path = null}); /// /// Gets the specified request. diff --git a/MediaBrowser.Model/IO/IFileSystem.cs b/MediaBrowser.Model/IO/IFileSystem.cs index 6c9b2bd883..e0771245fd 100644 --- a/MediaBrowser.Model/IO/IFileSystem.cs +++ b/MediaBrowser.Model/IO/IFileSystem.cs @@ -113,8 +113,6 @@ namespace MediaBrowser.Model.IO Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, FileOpenOptions fileOpenOptions); - string DefaultDirectory { get; } - /// /// Swaps the files. /// From c607c95e642d54ef0c8f191ab107d851fbab76bd Mon Sep 17 00:00:00 2001 From: William Taylor Date: Sun, 17 Feb 2019 14:33:20 +0000 Subject: [PATCH 100/104] Removed async from non-async method --- Jellyfin.Server/Program.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index b822815542..2a2f1dde62 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -82,7 +82,7 @@ namespace Jellyfin.Server appConfig = await CreateConfiguration(appPaths).ConfigureAwait(false); - await CreateLogger(appConfig, appPaths).ConfigureAwait(false); + CreateLogger(appConfig, appPaths); _logger = _loggerFactory.CreateLogger("Main"); @@ -338,7 +338,7 @@ namespace Jellyfin.Server .Build(); } - private static async Task CreateLogger(IConfiguration configuration, IApplicationPaths appPaths) + private static void CreateLogger(IConfiguration configuration, IApplicationPaths appPaths) { try { From 77a5617774eaf20314a40620fcb0b63d4cb17963 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 6 Feb 2019 20:53:05 +0100 Subject: [PATCH 101/104] Removed remaining self-update code --- Emby.Notifications/CoreNotificationTypes.cs | 32 ++++--------------- Emby.Notifications/Notifications.cs | 4 +-- .../AppBase/BaseApplicationPaths.cs | 6 ---- .../ApplicationHost.cs | 22 ------------- .../Configuration/IApplicationPaths.cs | 6 ---- MediaBrowser.Common/IApplicationHost.cs | 12 ------- MediaBrowser.Model/System/SystemInfo.cs | 6 ---- 7 files changed, 8 insertions(+), 80 deletions(-) diff --git a/Emby.Notifications/CoreNotificationTypes.cs b/Emby.Notifications/CoreNotificationTypes.cs index 8cc14fa012..0f9fc08d99 100644 --- a/Emby.Notifications/CoreNotificationTypes.cs +++ b/Emby.Notifications/CoreNotificationTypes.cs @@ -11,101 +11,81 @@ namespace Emby.Notifications public class CoreNotificationTypes : INotificationTypeFactory { private readonly ILocalizationManager _localization; - private readonly IServerApplicationHost _appHost; - public CoreNotificationTypes(ILocalizationManager localization, IServerApplicationHost appHost) + public CoreNotificationTypes(ILocalizationManager localization) { _localization = localization; - _appHost = appHost; } public IEnumerable GetNotificationTypes() { - var knownTypes = new List + var knownTypes = new NotificationTypeInfo[] { new NotificationTypeInfo { Type = NotificationType.ApplicationUpdateInstalled.ToString() }, - new NotificationTypeInfo { Type = NotificationType.InstallationFailed.ToString() }, - new NotificationTypeInfo { Type = NotificationType.PluginInstalled.ToString() }, - new NotificationTypeInfo { Type = NotificationType.PluginError.ToString() }, - new NotificationTypeInfo { Type = NotificationType.PluginUninstalled.ToString() }, - new NotificationTypeInfo { Type = NotificationType.PluginUpdateInstalled.ToString() }, - new NotificationTypeInfo { Type = NotificationType.ServerRestartRequired.ToString() }, - new NotificationTypeInfo { Type = NotificationType.TaskFailed.ToString() }, - new NotificationTypeInfo { Type = NotificationType.NewLibraryContent.ToString() }, - new NotificationTypeInfo { Type = NotificationType.AudioPlayback.ToString() }, - new NotificationTypeInfo { Type = NotificationType.VideoPlayback.ToString() }, - new NotificationTypeInfo { Type = NotificationType.AudioPlaybackStopped.ToString() }, - new NotificationTypeInfo { Type = NotificationType.VideoPlaybackStopped.ToString() }, - new NotificationTypeInfo { Type = NotificationType.CameraImageUploaded.ToString() }, - new NotificationTypeInfo { Type = NotificationType.UserLockedOut.ToString() - } - }; - - if (!_appHost.CanSelfUpdate) - { - knownTypes.Add(new NotificationTypeInfo + }, + new NotificationTypeInfo { Type = NotificationType.ApplicationUpdateAvailable.ToString() - }); - } + } + }; foreach (var type in knownTypes) { diff --git a/Emby.Notifications/Notifications.cs b/Emby.Notifications/Notifications.cs index d3290479f4..449331f9c4 100644 --- a/Emby.Notifications/Notifications.cs +++ b/Emby.Notifications/Notifications.cs @@ -65,7 +65,7 @@ namespace Emby.Notifications _localization = localization; _activityManager = activityManager; - _coreNotificationTypes = new CoreNotificationTypes(localization, appHost).GetNotificationTypes().Select(i => i.Type).ToArray(); + _coreNotificationTypes = new CoreNotificationTypes(localization).GetNotificationTypes().Select(i => i.Type).ToArray(); } public Task RunAsync() @@ -127,7 +127,7 @@ namespace Emby.Notifications async void _appHost_HasUpdateAvailableChanged(object sender, EventArgs e) { // This notification is for users who can't auto-update (aka running as service) - if (!_appHost.HasUpdateAvailable || _appHost.CanSelfUpdate) + if (!_appHost.HasUpdateAvailable) { return; } diff --git a/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs b/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs index f26cc4f62e..65cdccfa5d 100644 --- a/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs +++ b/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs @@ -72,12 +72,6 @@ namespace Emby.Server.Implementations.AppBase /// The plugin configurations path. public string PluginConfigurationsPath => Path.Combine(PluginsPath, "configurations"); - /// - /// Gets the path to where temporary update files will be stored - /// - /// The plugin configurations path. - public string TempUpdatePath => Path.Combine(ProgramDataPath, "updates"); - /// /// Gets the path to the log directory /// diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index ae020826de..fa8cc5c7e2 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -123,12 +123,6 @@ namespace Emby.Server.Implementations /// true if this instance can self restart; otherwise, false. public abstract bool CanSelfRestart { get; } - /// - /// Gets or sets a value indicating whether this instance can self update. - /// - /// true if this instance can self update; otherwise, false. - public virtual bool CanSelfUpdate => false; - public virtual bool CanLaunchWebBrowser { get @@ -1458,7 +1452,6 @@ namespace Emby.Server.Implementations OperatingSystem = EnvironmentInfo.OperatingSystem.ToString(), OperatingSystemDisplayName = EnvironmentInfo.OperatingSystemName, CanSelfRestart = CanSelfRestart, - CanSelfUpdate = CanSelfUpdate, CanLaunchWebBrowser = CanLaunchWebBrowser, WanAddress = wanAddress, HasUpdateAvailable = HasUpdateAvailable, @@ -1757,21 +1750,6 @@ namespace Emby.Server.Implementations Plugins = list.ToArray(); } - /// - /// Updates the application. - /// - /// The package that contains the update - /// The cancellation token. - /// The progress. - public async Task UpdateApplication(PackageVersionInfo package, CancellationToken cancellationToken, IProgress progress) - { - await InstallationManager.InstallPackage(package, false, progress, cancellationToken).ConfigureAwait(false); - - HasUpdateAvailable = false; - - OnApplicationUpdated(package); - } - /// /// This returns localhost in the case of no external dns, and the hostname if the /// dns is prefixed with a valid Uri prefix. diff --git a/MediaBrowser.Common/Configuration/IApplicationPaths.cs b/MediaBrowser.Common/Configuration/IApplicationPaths.cs index 27092c0e1a..cb4e8bf5f0 100644 --- a/MediaBrowser.Common/Configuration/IApplicationPaths.cs +++ b/MediaBrowser.Common/Configuration/IApplicationPaths.cs @@ -41,12 +41,6 @@ namespace MediaBrowser.Common.Configuration /// The plugin configurations path. string PluginConfigurationsPath { get; } - /// - /// Gets the path to where temporary update files will be stored - /// - /// The plugin configurations path. - string TempUpdatePath { get; } - /// /// Gets the path to the log directory /// diff --git a/MediaBrowser.Common/IApplicationHost.cs b/MediaBrowser.Common/IApplicationHost.cs index 6891152ee2..3a4098612d 100644 --- a/MediaBrowser.Common/IApplicationHost.cs +++ b/MediaBrowser.Common/IApplicationHost.cs @@ -72,12 +72,6 @@ namespace MediaBrowser.Common /// The application user agent. string ApplicationUserAgent { get; } - /// - /// Gets or sets a value indicating whether this instance can self update. - /// - /// true if this instance can self update; otherwise, false. - bool CanSelfUpdate { get; } - /// /// Gets the exports. /// @@ -86,12 +80,6 @@ namespace MediaBrowser.Common /// IEnumerable{``0}. IEnumerable GetExports(bool manageLifetime = true); - /// - /// Updates the application. - /// - /// Task. - Task UpdateApplication(PackageVersionInfo package, CancellationToken cancellationToken, IProgress progress); - /// /// Resolves this instance. /// diff --git a/MediaBrowser.Model/System/SystemInfo.cs b/MediaBrowser.Model/System/SystemInfo.cs index d9ed68b27e..581a1069cd 100644 --- a/MediaBrowser.Model/System/SystemInfo.cs +++ b/MediaBrowser.Model/System/SystemInfo.cs @@ -60,12 +60,6 @@ namespace MediaBrowser.Model.System /// true if this instance can self restart; otherwise, false. public bool CanSelfRestart { get; set; } - /// - /// Gets or sets a value indicating whether this instance can self update. - /// - /// true if this instance can self update; otherwise, false. - public bool CanSelfUpdate { get; set; } - public bool CanLaunchWebBrowser { get; set; } /// From 25253cf961e4309cef49612f1a729ab69507b604 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 6 Feb 2019 21:00:21 +0100 Subject: [PATCH 102/104] Fix style issues in changed files --- Emby.Notifications/Notifications.cs | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/Emby.Notifications/Notifications.cs b/Emby.Notifications/Notifications.cs index 449331f9c4..7defd8510e 100644 --- a/Emby.Notifications/Notifications.cs +++ b/Emby.Notifications/Notifications.cs @@ -5,21 +5,17 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Updates; using MediaBrowser.Controller; -using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Notifications; using MediaBrowser.Controller.Plugins; -using MediaBrowser.Controller.Session; using MediaBrowser.Model.Activity; using MediaBrowser.Model.Events; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Notifications; -using MediaBrowser.Model.Tasks; using Microsoft.Extensions.Logging; namespace Emby.Notifications @@ -29,39 +25,36 @@ namespace Emby.Notifications /// public class Notifications : IServerEntryPoint { - private readonly IInstallationManager _installationManager; - private readonly IUserManager _userManager; private readonly ILogger _logger; - private readonly ITaskManager _taskManager; private readonly INotificationManager _notificationManager; private readonly ILibraryManager _libraryManager; - private readonly ISessionManager _sessionManager; private readonly IServerApplicationHost _appHost; private Timer LibraryUpdateTimer { get; set; } private readonly object _libraryChangedSyncLock = new object(); private readonly IConfigurationManager _config; - private readonly IDeviceManager _deviceManager; private readonly ILocalizationManager _localization; private readonly IActivityManager _activityManager; private string[] _coreNotificationTypes; - public Notifications(IInstallationManager installationManager, IActivityManager activityManager, ILocalizationManager localization, IUserManager userManager, ILogger logger, ITaskManager taskManager, INotificationManager notificationManager, ILibraryManager libraryManager, ISessionManager sessionManager, IServerApplicationHost appHost, IConfigurationManager config, IDeviceManager deviceManager) + public Notifications( + IActivityManager activityManager, + ILocalizationManager localization, + ILogger logger, + INotificationManager notificationManager, + ILibraryManager libraryManager, + IServerApplicationHost appHost, + IConfigurationManager config) { - _installationManager = installationManager; - _userManager = userManager; _logger = logger; - _taskManager = taskManager; _notificationManager = notificationManager; _libraryManager = libraryManager; - _sessionManager = sessionManager; _appHost = appHost; _config = config; - _deviceManager = deviceManager; _localization = localization; _activityManager = activityManager; @@ -124,7 +117,7 @@ namespace Emby.Notifications return _config.GetConfiguration("notifications"); } - async void _appHost_HasUpdateAvailableChanged(object sender, EventArgs e) + private async void _appHost_HasUpdateAvailableChanged(object sender, EventArgs e) { // This notification is for users who can't auto-update (aka running as service) if (!_appHost.HasUpdateAvailable) @@ -145,7 +138,7 @@ namespace Emby.Notifications } private readonly List _itemsAdded = new List(); - void _libraryManager_ItemAdded(object sender, ItemChangeEventArgs e) + private void _libraryManager_ItemAdded(object sender, ItemChangeEventArgs e) { if (!FilterItem(e.Item)) { From 7554f6355195443b721a9b65f04ef4f9f4c097e9 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 9 Feb 2019 15:55:23 +0100 Subject: [PATCH 103/104] Remove more self-update code --- Emby.Notifications/Notifications.cs | 1 - .../ScheduledTasks/ScheduledTaskService.cs | 16 ++-------------- .../BaseApplicationConfiguration.cs | 15 --------------- 3 files changed, 2 insertions(+), 30 deletions(-) diff --git a/Emby.Notifications/Notifications.cs b/Emby.Notifications/Notifications.cs index 7defd8510e..ec08fd1935 100644 --- a/Emby.Notifications/Notifications.cs +++ b/Emby.Notifications/Notifications.cs @@ -119,7 +119,6 @@ namespace Emby.Notifications private async void _appHost_HasUpdateAvailableChanged(object sender, EventArgs e) { - // This notification is for users who can't auto-update (aka running as service) if (!_appHost.HasUpdateAvailable) { return; diff --git a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs index 16b036912c..b7e94b73f2 100644 --- a/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs +++ b/MediaBrowser.Api/ScheduledTasks/ScheduledTaskService.cs @@ -197,16 +197,6 @@ namespace MediaBrowser.Api.ScheduledTasks throw new ResourceNotFoundException("Task not found"); } - if (string.Equals(task.ScheduledTask.Key, "SystemUpdateTask", StringComparison.OrdinalIgnoreCase)) - { - // This is a hack for now just to get the update application function to work when auto-update is disabled - if (!_config.Configuration.EnableAutoUpdate) - { - _config.Configuration.EnableAutoUpdate = true; - _config.SaveConfiguration(); - } - } - TaskManager.Execute(task, new TaskOptions()); } @@ -238,16 +228,14 @@ namespace MediaBrowser.Api.ScheduledTasks // https://code.google.com/p/servicestack/source/browse/trunk/Common/ServiceStack.Text/ServiceStack.Text/Controller/PathInfo.cs var id = GetPathValue(1); - var task = TaskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, id)); + var task = TaskManager.ScheduledTasks.FirstOrDefault(i => string.Equals(i.Id, id, StringComparison.Ordinal)); if (task == null) { throw new ResourceNotFoundException("Task not found"); } - var triggerInfos = request; - - task.Triggers = triggerInfos.ToArray(); + task.Triggers = request.ToArray(); } } } diff --git a/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs b/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs index ce4ef1cfe4..6a1a0f0901 100644 --- a/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs +++ b/MediaBrowser.Model/Configuration/BaseApplicationConfiguration.cs @@ -7,20 +7,6 @@ namespace MediaBrowser.Model.Configuration /// public class BaseApplicationConfiguration { - // TODO: @bond Remove? - /// - /// Gets or sets a value indicating whether [enable debug level logging]. - /// - /// true if [enable debug level logging]; otherwise, false. - public bool EnableDebugLevelLogging { get; set; } - - /// - /// Enable automatically and silently updating of the application - /// - /// true if [enable auto update]; otherwise, false. - public bool EnableAutoUpdate { get; set; } - - // TODO: @bond Remove? /// /// The number of days we should retain log files /// @@ -44,7 +30,6 @@ namespace MediaBrowser.Model.Configuration /// public BaseApplicationConfiguration() { - EnableAutoUpdate = true; LogFileRetentionDays = 3; } } From 2ad54cd09df56335f962da00b64af6ff331ccefb Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Tue, 19 Feb 2019 01:18:49 +0100 Subject: [PATCH 104/104] Fixed the assemblynames from drone since, the namespaces do not line up (yet). --- .drone.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.drone.yml b/.drone.yml index 972bf36f3a..7705f4f936 100644 --- a/.drone.yml +++ b/.drone.yml @@ -90,22 +90,22 @@ steps: image: microsoft/dotnet:2-runtime err_ignore: true commands: - - dotnet ci/ci-tools/CompatibilityCheckerCoreCLI.dll ci/nuget-packages/Jellyfin.Common.dll ci/ci-release/Jellyfin.Common.dll + - dotnet ci/ci-tools/CompatibilityCheckerCoreCLI.dll ci/nuget-packages/MediaBrowser.Common.dll ci/ci-release/MediaBrowser.Common.dll - name: run-dotnet-compat-model image: microsoft/dotnet:2-runtime err_ignore: true commands: - - dotnet ci/ci-tools/CompatibilityCheckerCoreCLI.dll ci/nuget-packages/Jellyfin.Model.dll ci/ci-release/Jellyfin.Model.dll + - dotnet ci/ci-tools/CompatibilityCheckerCoreCLI.dll ci/nuget-packages/MediaBrowser.Model.dll ci/ci-release/MediaBrowser.Model.dll - name: run-dotnet-compat-controller image: microsoft/dotnet:2-runtime err_ignore: true commands: - - dotnet ci/ci-tools/CompatibilityCheckerCoreCLI.dll ci/nuget-packages/Jellyfin.Controller.dll ci/ci-release/Jellyfin.Controller.dll + - dotnet ci/ci-tools/CompatibilityCheckerCoreCLI.dll ci/nuget-packages/MediaBrowser.Controller.dll ci/ci-release/MediaBrowser.Controller.dll - name: run-dotnet-compat-naming image: microsoft/dotnet:2-runtime err_ignore: true commands: - - dotnet ci/ci-tools/CompatibilityCheckerCoreCLI.dll ci/nuget-packages/Jellyfin.Naming.dll ci/ci-release/Jellyfin.Naming.dll + - dotnet ci/ci-tools/CompatibilityCheckerCoreCLI.dll ci/nuget-packages/Emby.Naming.dll ci/ci-release/Emby.Naming.dll