From a6a4cd5667fbb5a793cb9e551ce9c9a9bfb0d44b Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Wed, 6 Feb 2019 20:38:42 +0100 Subject: [PATCH 001/101] 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 4360ff1d4..6759ed55a 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 6e91f6e40..1cc629b1d 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 d840542ba..e1097b23d 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 a6fc53953..943caa3e6 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 f3457d105..a4179e660 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 460809e93..d7fa4d4c2 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 3faad76e7..90b97061f 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 bb475eb2c..5c7133d05 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 1135cf694..6b0fd2dc6 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 6aeadda2f..cdfb5cadf 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 812e48a1f..2b99e0ddf 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 dcfe14943..f7743a3c2 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 866bd137f..495c3436a 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 ec3649bca..7d6529a67 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 983eb51e6..2233d3d40 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 6167d1eaa..bbf51dd24 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 3668f6a7a..73242d0ad 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 607a4d333..d47342511 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 80f746c7a..c644d13ea 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 064006ebd..87809cae8 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 d992f8d03..541b13cbe 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 472a3f105..848563679 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 a3298c580..db270c398 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 fed0904d1..a6d18c9b5 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 60752a85d..68d5d8b2d 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 3ff84382f..15cbbdb5a 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 0ea543ba0..7899cf01b 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 84ca130b7..fceb82ba1 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 eed239514..9a9bae215 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 6b02eaea8..b825ea3b0 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 d2ad65a1e..520b44404 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 1dcb02f43..3c807a8ea 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 6d1eff187..715f600a1 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 77b09a83d..24b100edd 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 638796e2e..fdaaf0bae 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 9a01c42d3..e66f5b42e 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/101] 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 70c309674..294748b77 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 7f3f12b00..d5872e4a7 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 851c40044..343d23e91 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/101] 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 98db4884b..5493e427c 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 b2891188d..5034f364e 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/101] 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 5493e427c..82a9ce7da 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/101] 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 82a9ce7da..95fe94e70 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/101] 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 befddb2e7..d21e3b532 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 2f4a00d322e355babfc73aa5d9e546491a02fad8 Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Sun, 10 Feb 2019 17:29:55 -0500 Subject: [PATCH 007/101] 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 bb475eb2c..353824406 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 dc7f57f27..127b9c62a 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 d8cb34dbbc3d4c86794836cb48116bebd885f0e5 Mon Sep 17 00:00:00 2001 From: William Lees Date: Tue, 12 Feb 2019 00:24:00 +1100 Subject: [PATCH 008/101] 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 073686298..693a69e1b 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 208a5560d..48b4e2f24 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 c197de173..7f4f8af0b 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 a0ea5c62d..7aeb0e9e8 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 e07770a4c..f97e88e98 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 009/101] 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 1acc42ea5..77ebc6e8f 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 45f003cae..98648d497 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 eb1bbfb74..60fb72d44 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 f97e88e98..8d0aef721 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 010/101] 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 127b9c62a..f03a594cd 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 011/101] 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 f03a594cd..adf609e20 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 012/101] 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 adf609e20..301802b8a 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 013/101] 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 693a69e1b..a6be071b8 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 77ebc6e8f..1acc42ea5 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 98648d497..45f003cae 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 60fb72d44..eb1bbfb74 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 7f4f8af0b..6a98c5e8a 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 8d0aef721..f97e88e98 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 014/101] 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 6c6e09ab1..586e322e4 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 015/101] Add to contributors --- CONTRIBUTORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 5e3455fba..28690f36f 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 016/101] 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 45e543525..ffd6de2d6 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 95fe94e70..f1212d3f9 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 aef666272..65e47747e 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 017/101] 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 589753c44..ad6b16047 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 018/101] 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 7004d44db..51f3a46a6 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 019/101] 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 f19cd532b..aa855ed21 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 020/101] 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 aa9a1add3..52afb4e49 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 021/101] 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 d2d16b18f..911fe36db 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 022/101] 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 b3d9c16cf..a5f1e8f94 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 023/101] 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 c01bb0c50..c10fbe58f 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 024/101] 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 ad6b16047..4bb9e9cfe 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 025/101] 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 4bb9e9cfe..531a9eb44 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 026/101] 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 531a9eb44..24af1839f 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 027/101] 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 332902292..67d4068cf 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 028/101] 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 d799fa50b..91fba4bbb 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 029/101] 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 91fba4bbb..c0465def8 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 64d5ec12e260758c4a7b3e9df85212b51dab8444 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Fri, 8 Feb 2019 22:59:28 +0100 Subject: [PATCH 030/101] 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 0f432c36c..a6be0da58 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 3014e482d..a0abd6ea0 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 064006ebd..6218d3a08 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 3ff84382f..22a593d49 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 451ee72dd..a037357ed 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 3ae7da007..46d7c250e 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 031/101] 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 a6be0da58..556b7a547 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 a0abd6ea0..6a346f31f 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 6218d3a08..e55f88550 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 b1515df43..885709b0c 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 651da1939..7a8455ff2 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 471b41127..e3c9ae58e 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 baf570d50..0c04d02dd 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 4fcc3aa53..94f5262b0 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 d317f9f38..c26457778 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 4e2483a56..890acc931 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 60c183d04..ab1f5a6b5 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 5156fce11..3cb0b7639 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 032/101] 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 6a346f31f..c7bcb6fa3 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 e55f88550..378693a43 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 ab1f5a6b5..511356aa4 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 3cb0b7639..47e0f3453 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 033/101] 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 c7bcb6fa3..49a510a22 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 7af50c329..a26f59573 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 034/101] 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 49a510a22..7e106569b 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 035/101] 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 7e106569b..6502e4aed 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 036/101] 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 7445fd3c2..e7e3308dc 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 3269d44cf..cb2e3580b 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 a36302876..f7ef16fb0 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 44898d498..8ae7fd90c 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 885709b0c..c7e1461bd 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 ebeb18ea0..12ae8169d 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 46d7c250e..96b0aa003 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 ae0cf6f36..18f51f652 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 037/101] 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 12ae8169d..d86293154 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 038/101] 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 c7e1461bd..fcfeeb225 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 039/101] 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 e7e3308dc..85a08b05a 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 fcfeeb225..b1515df43 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 d86293154..c2b71e9ef 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 3f878d63a5ffd878cf37c3086a2a4a7b3bd8a891 Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Tue, 12 Feb 2019 22:44:01 +0100 Subject: [PATCH 040/101] 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 f1212d3f9..972bf36f3 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 041/101] 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 ae256f79d..130a6ac05 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 042/101] 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 51f3a46a6..9d4d74099 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 043/101] 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 7bd2e90fe..6fd63a514 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 044/101] 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 911fe36db..c0f988abe 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 045/101] 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 130a6ac05..a122f1f09 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 046/101] 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 5d118d21f..1850b8f25 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 047/101] 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 d5872e4a7..3db3f4953 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 343d23e91..4565c5111 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 048/101] 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 556b7a547..fba81306b 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 c720504e39bae53c624f81b5df690e0088457789 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Wed, 13 Feb 2019 21:08:59 +0100 Subject: [PATCH 049/101] 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 7445fd3c2..75ca57ebb 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 a54de12be..7a179913a 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 050/101] 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 037cdd8aa..b62c5e1d4 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 051/101] 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 3db3f4953..a4b55a4ec 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 4565c5111..03fc0b6ff 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 8414285b588a41e50942deba171d852960b8907e Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Thu, 14 Feb 2019 09:15:37 -0500 Subject: [PATCH 052/101] 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 74bebeaf1..88d10438b 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 7bb8985f11569905af4edbf4c47cba4d9b32c7ca Mon Sep 17 00:00:00 2001 From: Anders Thomsen Date: Thu, 14 Feb 2019 21:53:04 +0100 Subject: [PATCH 053/101] 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 6cce312ee..28e70d046 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 054/101] 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 a122f1f09..658d168e9 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 055/101] 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 6ea1bd08e..2232b3eeb 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 056/101] 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 000000000..dbc7e4ad9 --- /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 000000000..89a3a9475 --- /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 74586417d..eed29aef3 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 851c40044..262b9203a 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 057/101] 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 dbc7e4ad9..84b98a011 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 89a3a9475..e8301c989 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 262b9203a..851c40044 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 058/101] 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 844f77a1a..303a8ac7b 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 774ed09da..a5badacee 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 fa8c89e88..7e4b38b4c 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 81fdb96d2..2f07ff15a 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 271188314..16507466f 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 942e84704..46e0dd918 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 387ccad25..beb2fb11d 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 0df46c399..43f3c5a22 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 4180a4f15..442a18cb9 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 c6c1a2a94..4d12b2f4a 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 b9c5d7ce5..20b53d58a 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 8b01ff342..93412306f 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 fd969c7c2..993581cca 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 a430e1041..b739c5765 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 b28d2a548..30ce5c64c 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 d0749405b..dee3030af 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 44590515e..3d7745085 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 21ee8f92f..a3e48d30d 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 a0ffd1ccf..4b6649217 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 ebeb18ea0..37fc6fe12 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 cabc96b23..68995a819 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 062/101] 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 68995a819..a4e6aac35 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 063/101] Disable SA1512 --- jellyfin.ruleset | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jellyfin.ruleset b/jellyfin.ruleset index 0f8c9aa02..295a45dc9 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 064/101] 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 37fc6fe12..a0f9e6d2d 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 a4e6aac35..6de678b86 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 065/101] 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 af8fe9616..4bb2e8e19 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 a0f9e6d2d..c5fdf6a3b 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 066/101] 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 a486c2a47..126cb467f 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 067/101] 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 fe1397bcb..a6bf23f5b 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 6dfabc364..ac5aab460 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 4bb2e8e19..584d38bcb 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 e7e36e31b..5b233cdf5 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 068/101] Disable SA1130 --- jellyfin.ruleset | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jellyfin.ruleset b/jellyfin.ruleset index 295a45dc9..25d11d7d3 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 069/101] 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 584d38bcb..9a0601750 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 c5fdf6a3b..a19ea6bf7 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 070/101] 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 4b6649217..90bd981f5 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 071/101] 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 9a0601750..dd38b058b 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 5b233cdf5..6eee4cd12 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 90bd981f5..58c4d38a2 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 a19ea6bf7..cbce7d457 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 072/101] 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 a6bf23f5b..1f2287a75 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 25d11d7d3..4381349ca 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 073/101] 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 dd38b058b..fe8e8242a 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 6de678b86..56e5c73d6 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 074/101] 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 1f2287a75..bd670df52 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 075/101] 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 fe8e8242a..24cf994ea 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 076/101] 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 a4b55a4ec..d0bdbd513 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 03fc0b6ff..a017fcd8e 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 077/101] 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 d0bdbd513..e3cbcc849 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 078/101] 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 094c1deae..f7e5946c7 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 079/101] 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 039274197..0dc37a644 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 06ba21b91..ec42610c0 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 000000000..a08c740b3 --- /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 080/101] 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 266b59f1c..67505a57d 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 0dc37a644..802f45ff2 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 ec42610c0..3175c950c 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 081/101] 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 a08c740b3..2fd6136c5 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 fb6a901374e062297dd1d95fef9b34766f66d4a6 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Sat, 16 Feb 2019 11:37:25 +0100 Subject: [PATCH 082/101] Separate HttpPostedFile --- Jellyfin.Server/SocketSharp/HttpFile.cs | 4 + Jellyfin.Server/SocketSharp/HttpPostedFile.cs | 204 ++++++++++++++++ Jellyfin.Server/SocketSharp/RequestMono.cs | 218 +----------------- .../SocketSharp/WebSocketSharpResponse.cs | 70 +++--- 4 files changed, 248 insertions(+), 248 deletions(-) create mode 100644 Jellyfin.Server/SocketSharp/HttpPostedFile.cs diff --git a/Jellyfin.Server/SocketSharp/HttpFile.cs b/Jellyfin.Server/SocketSharp/HttpFile.cs index 89c75e536..448b666b6 100644 --- a/Jellyfin.Server/SocketSharp/HttpFile.cs +++ b/Jellyfin.Server/SocketSharp/HttpFile.cs @@ -6,9 +6,13 @@ namespace Jellyfin.Server.SocketSharp public class HttpFile : IHttpFile { public string Name { get; set; } + public string FileName { get; set; } + public long ContentLength { get; set; } + public string ContentType { get; set; } + public Stream InputStream { get; set; } } } diff --git a/Jellyfin.Server/SocketSharp/HttpPostedFile.cs b/Jellyfin.Server/SocketSharp/HttpPostedFile.cs new file mode 100644 index 000000000..f38ed848e --- /dev/null +++ b/Jellyfin.Server/SocketSharp/HttpPostedFile.cs @@ -0,0 +1,204 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Net; +using System.Text; +using System.Threading.Tasks; +using MediaBrowser.Model.Services; + +public sealed class HttpPostedFile : IDisposable +{ + private string _name; + private string _contentType; + private Stream _stream; + private bool _disposed = false; + + internal HttpPostedFile(string name, string content_type, Stream base_stream, long offset, long length) + { + _name = name; + _contentType = content_type; + _stream = new ReadSubStream(base_stream, offset, length); + } + + public string ContentType => _contentType; + + public int ContentLength => (int)_stream.Length; + + public string FileName => _name; + + public Stream InputStream => _stream; + + /// + /// Releases the unmanaged resources and disposes of the managed resources used. + /// + public void Dispose() + { + if (_disposed) + { + return; + } + + _stream.Dispose(); + _stream = null; + + _name = null; + _contentType = null; + + _disposed = true; + } + + private class ReadSubStream : Stream + { + private Stream _stream; + private long _offset; + private long _end; + private long _position; + + public ReadSubStream(Stream s, long offset, long length) + { + _stream = s; + _offset = offset; + _end = offset + length; + _position = offset; + } + + public override void Flush() + { + } + + public override int Read(byte[] buffer, int dest_offset, int count) + { + if (buffer == null) + { + throw new ArgumentNullException(nameof(buffer)); + } + + if (dest_offset < 0) + { + throw new ArgumentOutOfRangeException(nameof(dest_offset), "< 0"); + } + + if (count < 0) + { + throw new ArgumentOutOfRangeException(nameof(count), "< 0"); + } + + int len = buffer.Length; + if (dest_offset > len) + { + throw new ArgumentException("destination offset is beyond array size", nameof(dest_offset)); + } + + // reordered to avoid possible integer overflow + if (dest_offset > len - count) + { + throw new ArgumentException("Reading would overrun buffer", nameof(count)); + } + + if (count > _end - _position) + { + count = (int)(_end - _position); + } + + if (count <= 0) + { + return 0; + } + + _stream.Position = _position; + int result = _stream.Read(buffer, dest_offset, count); + if (result > 0) + { + _position += result; + } + else + { + _position = _end; + } + + return result; + } + + public override int ReadByte() + { + if (_position >= _end) + { + return -1; + } + + _stream.Position = _position; + int result = _stream.ReadByte(); + if (result < 0) + { + _position = _end; + } + else + { + _position++; + } + + return result; + } + + public override long Seek(long d, SeekOrigin origin) + { + long real; + switch (origin) + { + case SeekOrigin.Begin: + real = _offset + d; + break; + case SeekOrigin.End: + real = _end + d; + break; + case SeekOrigin.Current: + real = _position + d; + break; + default: + throw new ArgumentException("Unknown SeekOrigin value", nameof(origin)); + } + + long virt = real - _offset; + if (virt < 0 || virt > Length) + { + throw new ArgumentException("Invalid position", nameof(d)); + } + + _position = _stream.Seek(real, SeekOrigin.Begin); + return _position; + } + + public override void SetLength(long value) + { + throw new NotSupportedException(); + } + + public override void Write(byte[] buffer, int offset, int count) + { + throw new NotSupportedException(); + } + + public override bool CanRead => true; + + public override bool CanSeek => true; + + public override bool CanWrite => false; + + public override long Length => _end - _offset; + + public override long Position + { + get => _position - _offset; + set + { + if (value > Length) + { + throw new ArgumentOutOfRangeException(nameof(value)); + } + + _position = Seek(value, SeekOrigin.Begin); + } + } + } +} diff --git a/Jellyfin.Server/SocketSharp/RequestMono.cs b/Jellyfin.Server/SocketSharp/RequestMono.cs index 24cf994ea..f2a08c9ae 100644 --- a/Jellyfin.Server/SocketSharp/RequestMono.cs +++ b/Jellyfin.Server/SocketSharp/RequestMono.cs @@ -225,7 +225,7 @@ namespace Jellyfin.Server.SocketSharp if (starts_with) { - return StrUtils.StartsWith(ContentType, ct, true); + return ContentType.StartsWith(ct, StringComparison.OrdinalIgnoreCase); } return string.Equals(ContentType, ct, StringComparison.OrdinalIgnoreCase); @@ -324,215 +324,6 @@ namespace Jellyfin.Server.SocketSharp return result.ToString(); } } - - public sealed class HttpPostedFile - { - private string name; - private string content_type; - private Stream stream; - - private class ReadSubStream : Stream - { - private Stream s; - private long offset; - private long end; - private long position; - - public ReadSubStream(Stream s, long offset, long length) - { - this.s = s; - this.offset = offset; - this.end = offset + length; - position = offset; - } - - public override void Flush() - { - } - - public override int Read(byte[] buffer, int dest_offset, int count) - { - if (buffer == null) - { - throw new ArgumentNullException(nameof(buffer)); - } - - if (dest_offset < 0) - { - throw new ArgumentOutOfRangeException(nameof(dest_offset), "< 0"); - } - - if (count < 0) - { - throw new ArgumentOutOfRangeException(nameof(count), "< 0"); - } - - int len = buffer.Length; - if (dest_offset > len) - { - throw new ArgumentException("destination offset is beyond array size", nameof(dest_offset)); - } - - // reordered to avoid possible integer overflow - if (dest_offset > len - count) - { - throw new ArgumentException("Reading would overrun buffer", nameof(count)); - } - - if (count > end - position) - { - count = (int)(end - position); - } - - if (count <= 0) - { - return 0; - } - - s.Position = position; - int result = s.Read(buffer, dest_offset, count); - if (result > 0) - { - position += result; - } - else - { - position = end; - } - - return result; - } - - public override int ReadByte() - { - if (position >= end) - { - return -1; - } - - s.Position = position; - int result = s.ReadByte(); - if (result < 0) - { - position = end; - } - else - { - position++; - } - - return result; - } - - public override long Seek(long d, SeekOrigin origin) - { - long real; - switch (origin) - { - case SeekOrigin.Begin: - real = offset + d; - break; - case SeekOrigin.End: - real = end + d; - break; - case SeekOrigin.Current: - real = position + d; - break; - default: - throw new ArgumentException("Unknown SeekOrigin value", nameof(origin)); - } - - long virt = real - offset; - if (virt < 0 || virt > Length) - { - throw new ArgumentException("Invalid position", nameof(d)); - } - - position = s.Seek(real, SeekOrigin.Begin); - return position; - } - - public override void SetLength(long value) - { - throw new NotSupportedException(); - } - - public override void Write(byte[] buffer, int offset, int count) - { - throw new NotSupportedException(); - } - - public override bool CanRead => true; - - public override bool CanSeek => true; - - public override bool CanWrite => false; - - public override long Length => end - offset; - - public override long Position - { - get => position - offset; - set - { - if (value > Length) - { - throw new ArgumentOutOfRangeException(nameof(value)); - } - - position = Seek(value, SeekOrigin.Begin); - } - } - } - - internal HttpPostedFile(string name, string content_type, Stream base_stream, long offset, long length) - { - this.name = name; - this.content_type = content_type; - this.stream = new ReadSubStream(base_stream, offset, length); - } - - public string ContentType => content_type; - - public int ContentLength => (int)stream.Length; - - public string FileName => name; - - public Stream InputStream => stream; - } - - internal static class StrUtils - { - public static bool StartsWith(string str1, string str2, bool ignore_case) - { - if (string.IsNullOrEmpty(str1)) - { - return false; - } - - var comparison = ignore_case ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - return str1.IndexOf(str2, comparison) == 0; - } - - public static bool EndsWith(string str1, string str2, bool ignore_case) - { - int l2 = str2.Length; - if (l2 == 0) - { - return true; - } - - int l1 = str1.Length; - if (l2 > l1) - { - return false; - } - - var comparison = ignore_case ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal; - return str1.IndexOf(str2, comparison) == str1.Length - str2.Length - 1; - } - } - private class HttpMultipart { @@ -606,12 +397,12 @@ namespace Jellyfin.Server.SocketSharp string header; while ((header = ReadHeaders()) != null) { - if (StrUtils.StartsWith(header, "Content-Disposition:", true)) + if (header.StartsWith("Content-Disposition:", StringComparison.OrdinalIgnoreCase)) { elem.Name = GetContentDispositionAttribute(header, "name"); elem.Filename = StripPath(GetContentDispositionAttributeWithEncoding(header, "filename")); } - else if (StrUtils.StartsWith(header, "Content-Type:", true)) + else if (header.StartsWith("Content-Type:", StringComparison.OrdinalIgnoreCase)) { elem.ContentType = header.Substring("Content-Type:".Length).Trim(); elem.Encoding = GetEncoding(elem.ContentType); @@ -730,13 +521,14 @@ namespace Jellyfin.Server.SocketSharp return false; } - if (!StrUtils.EndsWith(line, boundary, false)) + if (!line.EndsWith(boundary, StringComparison.Ordinal)) { return true; } } catch { + } return false; diff --git a/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs b/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs index 56e5c73d6..cf5aee5d4 100644 --- a/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs +++ b/Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs @@ -55,6 +55,41 @@ namespace Jellyfin.Server.SocketSharp public QueryParamCollection Headers => _response.Headers; + private static string AsHeaderValue(Cookie cookie) + { + DateTime defaultExpires = DateTime.MinValue; + + var path = cookie.Expires == defaultExpires + ? "/" + : cookie.Path ?? "/"; + + var sb = new StringBuilder(); + + sb.Append($"{cookie.Name}={cookie.Value};path={path}"); + + if (cookie.Expires != defaultExpires) + { + sb.Append($";expires={cookie.Expires:R}"); + } + + if (!string.IsNullOrEmpty(cookie.Domain)) + { + sb.Append($";domain={cookie.Domain}"); + } + + if (cookie.Secure) + { + sb.Append(";Secure"); + } + + if (cookie.HttpOnly) + { + sb.Append(";HttpOnly"); + } + + return sb.ToString(); + } + public void AddHeader(string name, string value) { if (string.Equals(name, "Content-Type", StringComparison.OrdinalIgnoreCase)) @@ -126,41 +161,6 @@ namespace Jellyfin.Server.SocketSharp _response.Headers.Add("Set-Cookie", cookieStr); } - public static string AsHeaderValue(Cookie cookie) - { - var defaultExpires = DateTime.MinValue; - - var path = cookie.Expires == defaultExpires - ? "/" - : cookie.Path ?? "/"; - - var sb = new StringBuilder(); - - sb.Append($"{cookie.Name}={cookie.Value};path={path}"); - - if (cookie.Expires != defaultExpires) - { - sb.Append($";expires={cookie.Expires:R}"); - } - - if (!string.IsNullOrEmpty(cookie.Domain)) - { - sb.Append($";domain={cookie.Domain}"); - } - - if (cookie.Secure) - { - sb.Append(";Secure"); - } - - if (cookie.HttpOnly) - { - sb.Append(";HttpOnly"); - } - - return sb.ToString(); - } - public bool SendChunked { get => _response.SendChunked; From a9934206761251a58d95c590bb87c9b0177e6754 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Sat, 16 Feb 2019 11:41:48 +0100 Subject: [PATCH 083/101] 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 784486d52..2490b9717 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 084/101] 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 e3cbcc849..869dc4a5e 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 a017fcd8e..75821cb17 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 085/101] 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 67505a57d..6c0d2515f 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 802f45ff2..9d1c30619 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 3175c950c..e61aaa167 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 086/101] 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 000000000..0483ad207 --- /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 6bf776f53..16258c767 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 7c44878ec..8ffb0f74a 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 ac5aab460..7236238c2 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 087/101] 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 0483ad207..b9b95d65d 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 088/101] 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 16258c767..bbf165d62 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 089/101] 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 784486d52..44c74ad5d 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 b9b95d65d..30bfd8749 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 834ffb130..d78891ac7 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 8ffb0f74a..a64dfb607 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 126cb467f..84d78d3fb 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 7236238c2..b82281554 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 bdd7a8f8f..f4813e713 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 6c9b2bd88..e0771245f 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 090/101] 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 b82281554..2a2f1dde6 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 091/101] 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 8cc14fa01..0f9fc08d9 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 d3290479f..449331f9c 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 f26cc4f62..65cdccfa5 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 ae020826d..fa8cc5c7e 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 27092c0e1..cb4e8bf5f 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 6891152ee..3a4098612 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 d9ed68b27..581a1069c 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 092/101] 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 449331f9c..7defd8510 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 093/101] 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 7defd8510..ec08fd193 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 16b036912..b7e94b73f 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 ce4ef1cfe..6a1a0f090 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 a94aeb5c8783a3f170d156a3663ea79200939108 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 9 Feb 2019 20:20:39 +0100 Subject: [PATCH 094/101] Simplify code to get data dir --- Jellyfin.Server/Program.cs | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index ac5aab460..7ab9f66cb 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -181,26 +181,13 @@ namespace Jellyfin.Server if (string.IsNullOrEmpty(dataDir)) { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) - { - dataDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); - } - else - { - // $XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored. - 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)) - { - dataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".local", "share"); - } - } - - dataDir = Path.Combine(dataDir, "jellyfin"); + // LocalApplicationData follows the XDG spec on unix machines + dataDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "jellyfin"); } } + Directory.CreateDirectory(dataDir); + // configDir // IF --configdir // ELSE IF $JELLYFIN_CONFIG_DIR @@ -210,7 +197,6 @@ namespace Jellyfin.Server // ELSE IF $XDG_CONFIG_HOME use $XDG_CONFIG_HOME/jellyfin // ELSE $HOME/.config/jellyfin var configDir = options.ConfigDir; - if (string.IsNullOrEmpty(configDir)) { configDir = Environment.GetEnvironmentVariable("JELLYFIN_CONFIG_DIR"); From 51ba28bd651079eb4f704739dcb17852537ddf55 Mon Sep 17 00:00:00 2001 From: Bond-009 Date: Mon, 18 Feb 2019 17:37:10 +0100 Subject: [PATCH 095/101] Remove useless check --- Jellyfin.Server/Program.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 7ab9f66cb..292fbb15a 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -280,7 +280,6 @@ namespace Jellyfin.Server // Ensure the main folders exist before we continue try { - Directory.CreateDirectory(dataDir); Directory.CreateDirectory(logDir); Directory.CreateDirectory(configDir); Directory.CreateDirectory(cacheDir); From 967d5deeb79405ce7122c6124dac019b278ca70b Mon Sep 17 00:00:00 2001 From: Felix Ruhnow Date: Mon, 18 Feb 2019 18:29:58 +0100 Subject: [PATCH 096/101] checking user-permission in GetQueryResult to prevent accessing the library without permission but having a link. (+added myself as contributor. forgot last time bout that) --- CONTRIBUTORS.md | 1 + MediaBrowser.Api/UserLibrary/ItemsService.cs | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 28690f36f..39149910c 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -19,6 +19,7 @@ - [LogicalPhallacy](https://github.com/LogicalPhallacy/) - [RazeLighter777](https://github.com/RazeLighter777) - [WillWill56](https://github.com/WillWill56) + - [fruhnow](https://github.com/fruhnow) # Emby Contributors diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index 3ae7da007..895c88dc8 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -12,6 +12,7 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Services; +using Microsoft.Extensions.Logging; namespace MediaBrowser.Api.UserLibrary { @@ -227,6 +228,16 @@ namespace MediaBrowser.Api.UserLibrary request.IncludeItemTypes = "Playlist"; } + if (!user.Policy.EnabledFolders.Where(i => new Guid(i).Equals(item.Id)).Any() && !user.Policy.EnableAllFolders) + { + Logger.LogWarning($"{user.Name} is not permitted to access Library {item.Name}."); + return new QueryResult + { + Items = new BaseItem[0], + TotalRecordCount = 0 + }; + } + if (request.Recursive || !string.IsNullOrEmpty(request.Ids) || user == null) { return folder.GetItems(GetItemsQuery(request, dtoOptions, user)); From 2ad54cd09df56335f962da00b64af6ff331ccefb Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Tue, 19 Feb 2019 01:18:49 +0100 Subject: [PATCH 097/101] 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 972bf36f3..7705f4f93 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 From 1d631540ace68a8079aba7f5a4d790397bcd3317 Mon Sep 17 00:00:00 2001 From: Felix Ruhnow Date: Tue, 19 Feb 2019 12:06:50 +0100 Subject: [PATCH 098/101] adressing pr comments --- MediaBrowser.Api/UserLibrary/ItemsService.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index 895c88dc8..aae86e416 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -228,12 +228,12 @@ namespace MediaBrowser.Api.UserLibrary request.IncludeItemTypes = "Playlist"; } - if (!user.Policy.EnabledFolders.Where(i => new Guid(i).Equals(item.Id)).Any() && !user.Policy.EnableAllFolders) + if (!user.Policy.EnableAllFolders && !user.Policy.EnabledFolders.Any(i => new Guid(i).Equals(item.Id))) { Logger.LogWarning($"{user.Name} is not permitted to access Library {item.Name}."); return new QueryResult { - Items = new BaseItem[0], + Items = Array.Empty(), TotalRecordCount = 0 }; } From ba003e06efd55bc599cbd8c29be6a41b21e3c35e Mon Sep 17 00:00:00 2001 From: Felix Ruhnow Date: Tue, 19 Feb 2019 12:09:39 +0100 Subject: [PATCH 099/101] adressing pr comments --- MediaBrowser.Api/UserLibrary/ItemsService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index aae86e416..dfd523fde 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -228,7 +228,7 @@ namespace MediaBrowser.Api.UserLibrary request.IncludeItemTypes = "Playlist"; } - if (!user.Policy.EnableAllFolders && !user.Policy.EnabledFolders.Any(i => new Guid(i).Equals(item.Id))) + if (!user.Policy.EnableAllFolders && !user.Policy.EnabledFolders.Any(i => new Guid(i) == item.Id)) { Logger.LogWarning($"{user.Name} is not permitted to access Library {item.Name}."); return new QueryResult From 53beebc77415d9020bedb385483851e7bb96a929 Mon Sep 17 00:00:00 2001 From: Felix Ruhnow Date: Tue, 19 Feb 2019 12:17:28 +0100 Subject: [PATCH 100/101] switching logging to serilog convention according to pr comments --- MediaBrowser.Api/UserLibrary/ItemsService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MediaBrowser.Api/UserLibrary/ItemsService.cs b/MediaBrowser.Api/UserLibrary/ItemsService.cs index dfd523fde..ba4e8022c 100644 --- a/MediaBrowser.Api/UserLibrary/ItemsService.cs +++ b/MediaBrowser.Api/UserLibrary/ItemsService.cs @@ -230,7 +230,7 @@ namespace MediaBrowser.Api.UserLibrary if (!user.Policy.EnableAllFolders && !user.Policy.EnabledFolders.Any(i => new Guid(i) == item.Id)) { - Logger.LogWarning($"{user.Name} is not permitted to access Library {item.Name}."); + Logger.LogWarning("{UserName} is not permitted to access Library {ItemName}.", user.Name, item.Name); return new QueryResult { Items = Array.Empty(), From dab25a0eebb077c567ec4934333be9a4e3ea9852 Mon Sep 17 00:00:00 2001 From: Claus Vium Date: Tue, 19 Feb 2019 21:17:30 +0100 Subject: [PATCH 101/101] Remove OptimizedPriorityQueue source and grab it from nuget --- .../Manager/GenericPriorityQueue.cs | 402 ------------------ .../Manager/GenericPriorityQueueNode.cs | 22 - .../Manager/IFixedSizePriorityQueue.cs | 24 -- .../Manager/IPriorityQueue.cs | 56 --- .../Manager/SimplePriorityQueue.cs | 247 ----------- .../MediaBrowser.Providers.csproj | 3 +- 6 files changed, 2 insertions(+), 752 deletions(-) delete mode 100644 MediaBrowser.Providers/Manager/GenericPriorityQueue.cs delete mode 100644 MediaBrowser.Providers/Manager/GenericPriorityQueueNode.cs delete mode 100644 MediaBrowser.Providers/Manager/IFixedSizePriorityQueue.cs delete mode 100644 MediaBrowser.Providers/Manager/IPriorityQueue.cs delete mode 100644 MediaBrowser.Providers/Manager/SimplePriorityQueue.cs diff --git a/MediaBrowser.Providers/Manager/GenericPriorityQueue.cs b/MediaBrowser.Providers/Manager/GenericPriorityQueue.cs deleted file mode 100644 index 10ff2515c..000000000 --- a/MediaBrowser.Providers/Manager/GenericPriorityQueue.cs +++ /dev/null @@ -1,402 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Runtime.CompilerServices; - -//TODO Fix namespace or replace -namespace Priority_Queue -{ - /// - /// Credit: https://github.com/BlueRaja/High-Speed-Priority-Queue-for-C-Sharp - /// A copy of StablePriorityQueue which also has generic priority-type - /// - /// The values in the queue. Must extend the GenericPriorityQueue class - /// The priority-type. Must extend IComparable<TPriority> - public sealed class GenericPriorityQueue : IFixedSizePriorityQueue - where TItem : GenericPriorityQueueNode - where TPriority : IComparable - { - private int _numNodes; - private TItem[] _nodes; - private long _numNodesEverEnqueued; - - /// - /// Instantiate a new Priority Queue - /// - /// The max nodes ever allowed to be enqueued (going over this will cause undefined behavior) - public GenericPriorityQueue(int maxNodes) - { -#if DEBUG - if (maxNodes <= 0) - { - throw new InvalidOperationException("New queue size cannot be smaller than 1"); - } -#endif - - _numNodes = 0; - _nodes = new TItem[maxNodes + 1]; - _numNodesEverEnqueued = 0; - } - - /// - /// Returns the number of nodes in the queue. - /// O(1) - /// - public int Count => _numNodes; - - /// - /// Returns the maximum number of items that can be enqueued at once in this queue. Once you hit this number (ie. once Count == MaxSize), - /// attempting to enqueue another item will cause undefined behavior. O(1) - /// - public int MaxSize => _nodes.Length - 1; - - /// - /// Removes every node from the queue. - /// O(n) (So, don't do this often!) - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Clear() - { - Array.Clear(_nodes, 1, _numNodes); - _numNodes = 0; - } - - /// - /// Returns (in O(1)!) whether the given node is in the queue. O(1) - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool Contains(TItem node) - { -#if DEBUG - if (node == null) - { - throw new ArgumentNullException(nameof(node)); - } - if (node.QueueIndex < 0 || node.QueueIndex >= _nodes.Length) - { - throw new InvalidOperationException("node.QueueIndex has been corrupted. Did you change it manually? Or add this node to another queue?"); - } -#endif - - return (_nodes[node.QueueIndex] == node); - } - - /// - /// Enqueue a node to the priority queue. Lower values are placed in front. Ties are broken by first-in-first-out. - /// If the queue is full, the result is undefined. - /// If the node is already enqueued, the result is undefined. - /// O(log n) - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Enqueue(TItem node, TPriority priority) - { -#if DEBUG - if (node == null) - { - throw new ArgumentNullException(nameof(node)); - } - if (_numNodes >= _nodes.Length - 1) - { - throw new InvalidOperationException("Queue is full - node cannot be added: " + node); - } - if (Contains(node)) - { - throw new InvalidOperationException("Node is already enqueued: " + node); - } -#endif - - node.Priority = priority; - _numNodes++; - _nodes[_numNodes] = node; - node.QueueIndex = _numNodes; - node.InsertionIndex = _numNodesEverEnqueued++; - CascadeUp(_nodes[_numNodes]); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void Swap(TItem node1, TItem node2) - { - //Swap the nodes - _nodes[node1.QueueIndex] = node2; - _nodes[node2.QueueIndex] = node1; - - //Swap their indicies - int temp = node1.QueueIndex; - node1.QueueIndex = node2.QueueIndex; - node2.QueueIndex = temp; - } - - //Performance appears to be slightly better when this is NOT inlined o_O - private void CascadeUp(TItem node) - { - //aka Heapify-up - int parent = node.QueueIndex / 2; - while (parent >= 1) - { - var parentNode = _nodes[parent]; - if (HasHigherPriority(parentNode, node)) - break; - - //Node has lower priority value, so move it up the heap - Swap(node, parentNode); //For some reason, this is faster with Swap() rather than (less..?) individual operations, like in CascadeDown() - - parent = node.QueueIndex / 2; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void CascadeDown(TItem node) - { - //aka Heapify-down - TItem newParent; - int finalQueueIndex = node.QueueIndex; - while (true) - { - newParent = node; - int childLeftIndex = 2 * finalQueueIndex; - - //Check if the left-child is higher-priority than the current node - if (childLeftIndex > _numNodes) - { - //This could be placed outside the loop, but then we'd have to check newParent != node twice - node.QueueIndex = finalQueueIndex; - _nodes[finalQueueIndex] = node; - break; - } - - var childLeft = _nodes[childLeftIndex]; - if (HasHigherPriority(childLeft, newParent)) - { - newParent = childLeft; - } - - //Check if the right-child is higher-priority than either the current node or the left child - int childRightIndex = childLeftIndex + 1; - if (childRightIndex <= _numNodes) - { - var childRight = _nodes[childRightIndex]; - if (HasHigherPriority(childRight, newParent)) - { - newParent = childRight; - } - } - - //If either of the children has higher (smaller) priority, swap and continue cascading - if (newParent != node) - { - //Move new parent to its new index. node will be moved once, at the end - //Doing it this way is one less assignment operation than calling Swap() - _nodes[finalQueueIndex] = newParent; - - int temp = newParent.QueueIndex; - newParent.QueueIndex = finalQueueIndex; - finalQueueIndex = temp; - } - else - { - //See note above - node.QueueIndex = finalQueueIndex; - _nodes[finalQueueIndex] = node; - break; - } - } - } - - /// - /// Returns true if 'higher' has higher priority than 'lower', false otherwise. - /// Note that calling HasHigherPriority(node, node) (ie. both arguments the same node) will return false - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private bool HasHigherPriority(TItem higher, TItem lower) - { - var cmp = higher.Priority.CompareTo(lower.Priority); - return (cmp < 0 || (cmp == 0 && higher.InsertionIndex < lower.InsertionIndex)); - } - - /// - /// Removes the head of the queue (node with minimum priority; ties are broken by order of insertion), and returns it. - /// If queue is empty, result is undefined - /// O(log n) - /// - public bool TryDequeue(out TItem item) - { - if (_numNodes <= 0) - { - item = default(TItem); - return false; - } - -#if DEBUG - - if (!IsValidQueue()) - { - throw new InvalidOperationException("Queue has been corrupted (Did you update a node priority manually instead of calling UpdatePriority()?" + - "Or add the same node to two different queues?)"); - } -#endif - - var returnMe = _nodes[1]; - Remove(returnMe); - item = returnMe; - return true; - } - - /// - /// Resize the queue so it can accept more nodes. All currently enqueued nodes are remain. - /// Attempting to decrease the queue size to a size too small to hold the existing nodes results in undefined behavior - /// O(n) - /// - public void Resize(int maxNodes) - { -#if DEBUG - if (maxNodes <= 0) - { - throw new InvalidOperationException("Queue size cannot be smaller than 1"); - } - - if (maxNodes < _numNodes) - { - throw new InvalidOperationException("Called Resize(" + maxNodes + "), but current queue contains " + _numNodes + " nodes"); - } -#endif - - TItem[] newArray = new TItem[maxNodes + 1]; - int highestIndexToCopy = Math.Min(maxNodes, _numNodes); - for (int i = 1; i <= highestIndexToCopy; i++) - { - newArray[i] = _nodes[i]; - } - _nodes = newArray; - } - - /// - /// Returns the head of the queue, without removing it (use Dequeue() for that). - /// If the queue is empty, behavior is undefined. - /// O(1) - /// - public TItem First - { - get - { -#if DEBUG - if (_numNodes <= 0) - { - throw new InvalidOperationException("Cannot call .First on an empty queue"); - } -#endif - - return _nodes[1]; - } - } - - /// - /// This method must be called on a node every time its priority changes while it is in the queue. - /// Forgetting to call this method will result in a corrupted queue! - /// Calling this method on a node not in the queue results in undefined behavior - /// O(log n) - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void UpdatePriority(TItem node, TPriority priority) - { -#if DEBUG - if (node == null) - { - throw new ArgumentNullException(nameof(node)); - } - if (!Contains(node)) - { - throw new InvalidOperationException("Cannot call UpdatePriority() on a node which is not enqueued: " + node); - } -#endif - - node.Priority = priority; - OnNodeUpdated(node); - } - - private void OnNodeUpdated(TItem node) - { - //Bubble the updated node up or down as appropriate - int parentIndex = node.QueueIndex / 2; - var parentNode = _nodes[parentIndex]; - - if (parentIndex > 0 && HasHigherPriority(node, parentNode)) - { - CascadeUp(node); - } - else - { - //Note that CascadeDown will be called if parentNode == node (that is, node is the root) - CascadeDown(node); - } - } - - /// - /// Removes a node from the queue. The node does not need to be the head of the queue. - /// If the node is not in the queue, the result is undefined. If unsure, check Contains() first - /// O(log n) - /// - public void Remove(TItem node) - { -#if DEBUG - if (node == null) - { - throw new ArgumentNullException(nameof(node)); - } - if (!Contains(node)) - { - throw new InvalidOperationException("Cannot call Remove() on a node which is not enqueued: " + node); - } -#endif - - //If the node is already the last node, we can remove it immediately - if (node.QueueIndex == _numNodes) - { - _nodes[_numNodes] = null; - _numNodes--; - return; - } - - //Swap the node with the last node - var formerLastNode = _nodes[_numNodes]; - Swap(node, formerLastNode); - _nodes[_numNodes] = null; - _numNodes--; - - //Now bubble formerLastNode (which is no longer the last node) up or down as appropriate - OnNodeUpdated(formerLastNode); - } - - public IEnumerator GetEnumerator() - { - for (int i = 1; i <= _numNodes; i++) - yield return _nodes[i]; - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - /// - /// Should not be called in production code. - /// Checks to make sure the queue is still in a valid state. Used for testing/debugging the queue. - /// - public bool IsValidQueue() - { - for (int i = 1; i < _nodes.Length; i++) - { - if (_nodes[i] != null) - { - int childLeftIndex = 2 * i; - if (childLeftIndex < _nodes.Length && _nodes[childLeftIndex] != null && HasHigherPriority(_nodes[childLeftIndex], _nodes[i])) - return false; - - int childRightIndex = childLeftIndex + 1; - if (childRightIndex < _nodes.Length && _nodes[childRightIndex] != null && HasHigherPriority(_nodes[childRightIndex], _nodes[i])) - return false; - } - } - return true; - } - } -} diff --git a/MediaBrowser.Providers/Manager/GenericPriorityQueueNode.cs b/MediaBrowser.Providers/Manager/GenericPriorityQueueNode.cs deleted file mode 100644 index b45ae0fd8..000000000 --- a/MediaBrowser.Providers/Manager/GenericPriorityQueueNode.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace Priority_Queue -{ - /// Credit: https://github.com/BlueRaja/High-Speed-Priority-Queue-for-C-Sharp - public class GenericPriorityQueueNode - { - /// - /// The Priority to insert this node at. Must be set BEFORE adding a node to the queue (ideally just once, in the node's constructor). - /// Should not be manually edited once the node has been enqueued - use queue.UpdatePriority() instead - /// - public TPriority Priority { get; protected internal set; } - - /// - /// Represents the current position in the queue - /// - public int QueueIndex { get; internal set; } - - /// - /// Represents the order the node was inserted in - /// - public long InsertionIndex { get; internal set; } - } -} diff --git a/MediaBrowser.Providers/Manager/IFixedSizePriorityQueue.cs b/MediaBrowser.Providers/Manager/IFixedSizePriorityQueue.cs deleted file mode 100644 index 509d98e42..000000000 --- a/MediaBrowser.Providers/Manager/IFixedSizePriorityQueue.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; - -namespace Priority_Queue -{ - /// - /// Credit: https://github.com/BlueRaja/High-Speed-Priority-Queue-for-C-Sharp - /// A helper-interface only needed to make writing unit tests a bit easier (hence the 'internal' access modifier) - /// - internal interface IFixedSizePriorityQueue : IPriorityQueue - where TPriority : IComparable - { - /// - /// Resize the queue so it can accept more nodes. All currently enqueued nodes are remain. - /// Attempting to decrease the queue size to a size too small to hold the existing nodes results in undefined behavior - /// - void Resize(int maxNodes); - - /// - /// Returns the maximum number of items that can be enqueued at once in this queue. Once you hit this number (ie. once Count == MaxSize), - /// attempting to enqueue another item will cause undefined behavior. - /// - int MaxSize { get; } - } -} diff --git a/MediaBrowser.Providers/Manager/IPriorityQueue.cs b/MediaBrowser.Providers/Manager/IPriorityQueue.cs deleted file mode 100644 index dc319a7f8..000000000 --- a/MediaBrowser.Providers/Manager/IPriorityQueue.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Priority_Queue -{ - /// - /// Credit: https://github.com/BlueRaja/High-Speed-Priority-Queue-for-C-Sharp - /// The IPriorityQueue interface. This is mainly here for purists, and in case I decide to add more implementations later. - /// For speed purposes, it is actually recommended that you *don't* access the priority queue through this interface, since the JIT can - /// (theoretically?) optimize method calls from concrete-types slightly better. - /// - public interface IPriorityQueue : IEnumerable - where TPriority : IComparable - { - /// - /// Enqueue a node to the priority queue. Lower values are placed in front. Ties are broken by first-in-first-out. - /// See implementation for how duplicates are handled. - /// - void Enqueue(TItem node, TPriority priority); - - /// - /// Removes the head of the queue (node with minimum priority; ties are broken by order of insertion), and returns it. - /// - bool TryDequeue(out TItem item); - - /// - /// Removes every node from the queue. - /// - void Clear(); - - /// - /// Returns whether the given node is in the queue. - /// - bool Contains(TItem node); - - /// - /// Removes a node from the queue. The node does not need to be the head of the queue. - /// - void Remove(TItem node); - - /// - /// Call this method to change the priority of a node. - /// - void UpdatePriority(TItem node, TPriority priority); - - /// - /// Returns the head of the queue, without removing it (use Dequeue() for that). - /// - TItem First { get; } - - /// - /// Returns the number of nodes in the queue. - /// - int Count { get; } - } -} diff --git a/MediaBrowser.Providers/Manager/SimplePriorityQueue.cs b/MediaBrowser.Providers/Manager/SimplePriorityQueue.cs deleted file mode 100644 index d064312cf..000000000 --- a/MediaBrowser.Providers/Manager/SimplePriorityQueue.cs +++ /dev/null @@ -1,247 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; - -namespace Priority_Queue -{ - /// - /// Credit: https://github.com/BlueRaja/High-Speed-Priority-Queue-for-C-Sharp - /// A simplified priority queue implementation. Is stable, auto-resizes, and thread-safe, at the cost of being slightly slower than - /// FastPriorityQueue - /// - /// The type to enqueue - /// The priority-type to use for nodes. Must extend IComparable<TPriority> - public class SimplePriorityQueue : IPriorityQueue - where TPriority : IComparable - { - private class SimpleNode : GenericPriorityQueueNode - { - public TItem Data { get; private set; } - - public SimpleNode(TItem data) - { - Data = data; - } - } - - private const int INITIAL_QUEUE_SIZE = 10; - private readonly GenericPriorityQueue _queue; - - public SimplePriorityQueue() - { - _queue = new GenericPriorityQueue(INITIAL_QUEUE_SIZE); - } - - /// - /// Given an item of type T, returns the exist SimpleNode in the queue - /// - private SimpleNode GetExistingNode(TItem item) - { - var comparer = EqualityComparer.Default; - foreach (var node in _queue) - { - if (comparer.Equals(node.Data, item)) - { - return node; - } - } - throw new InvalidOperationException("Item cannot be found in queue: " + item); - } - - /// - /// Returns the number of nodes in the queue. - /// O(1) - /// - public int Count - { - get - { - lock (_queue) - { - return _queue.Count; - } - } - } - - - /// - /// Returns the head of the queue, without removing it (use Dequeue() for that). - /// Throws an exception when the queue is empty. - /// O(1) - /// - public TItem First - { - get - { - lock (_queue) - { - if (_queue.Count <= 0) - { - throw new InvalidOperationException("Cannot call .First on an empty queue"); - } - - SimpleNode first = _queue.First; - return (first != null ? first.Data : default(TItem)); - } - } - } - - /// - /// Removes every node from the queue. - /// O(n) - /// - public void Clear() - { - lock (_queue) - { - _queue.Clear(); - } - } - - /// - /// Returns whether the given item is in the queue. - /// O(n) - /// - public bool Contains(TItem item) - { - lock (_queue) - { - var comparer = EqualityComparer.Default; - foreach (var node in _queue) - { - if (comparer.Equals(node.Data, item)) - { - return true; - } - } - return false; - } - } - - /// - /// Removes the head of the queue (node with minimum priority; ties are broken by order of insertion), and returns it. - /// If queue is empty, throws an exception - /// O(log n) - /// - public bool TryDequeue(out TItem item) - { - lock (_queue) - { - if (_queue.Count <= 0) - { - item = default(TItem); - return false; - } - - if (_queue.TryDequeue(out SimpleNode node)) - { - item = node.Data; - return true; - } - - item = default(TItem); - return false; - } - } - - /// - /// Enqueue a node to the priority queue. Lower values are placed in front. Ties are broken by first-in-first-out. - /// This queue automatically resizes itself, so there's no concern of the queue becoming 'full'. - /// Duplicates are allowed. - /// O(log n) - /// - public void Enqueue(TItem item, TPriority priority) - { - lock (_queue) - { - var node = new SimpleNode(item); - if (_queue.Count == _queue.MaxSize) - { - _queue.Resize(_queue.MaxSize * 2 + 1); - } - _queue.Enqueue(node, priority); - } - } - - /// - /// Removes an item from the queue. The item does not need to be the head of the queue. - /// If the item is not in the queue, an exception is thrown. If unsure, check Contains() first. - /// If multiple copies of the item are enqueued, only the first one is removed. - /// O(n) - /// - public void Remove(TItem item) - { - lock (_queue) - { - try - { - _queue.Remove(GetExistingNode(item)); - } - catch (InvalidOperationException ex) - { - throw new InvalidOperationException("Cannot call Remove() on a node which is not enqueued: " + item, ex); - } - } - } - - /// - /// Call this method to change the priority of an item. - /// Calling this method on a item not in the queue will throw an exception. - /// If the item is enqueued multiple times, only the first one will be updated. - /// (If your requirements are complex enough that you need to enqueue the same item multiple times and be able - /// to update all of them, please wrap your items in a wrapper class so they can be distinguished). - /// O(n) - /// - public void UpdatePriority(TItem item, TPriority priority) - { - lock (_queue) - { - try - { - SimpleNode updateMe = GetExistingNode(item); - _queue.UpdatePriority(updateMe, priority); - } - catch (InvalidOperationException ex) - { - throw new InvalidOperationException("Cannot call UpdatePriority() on a node which is not enqueued: " + item, ex); - } - } - } - - public IEnumerator GetEnumerator() - { - var queueData = new List(); - lock (_queue) - { - //Copy to a separate list because we don't want to 'yield return' inside a lock - foreach (var node in _queue) - { - queueData.Add(node.Data); - } - } - - return queueData.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - - public bool IsValidQueue() - { - lock (_queue) - { - return _queue.IsValidQueue(); - } - } - } - - /// - /// A simplified priority queue implementation. Is stable, auto-resizes, and thread-safe, at the cost of being slightly slower than - /// FastPriorityQueue - /// This class is kept here for backwards compatibility. It's recommended you use Simple - /// - /// The type to enqueue - public class SimplePriorityQueue : SimplePriorityQueue { } -} diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index e6ef889c3..7b8d629ee 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -1,4 +1,4 @@ - + @@ -11,6 +11,7 @@ +