aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations
diff options
context:
space:
mode:
authorBond_009 <bond.009@outlook.com>2020-01-10 21:16:46 +0100
committerBond_009 <bond.009@outlook.com>2020-01-10 21:16:46 +0100
commite714b9930ef27e5a1ea870e04e2241eb7cf1fce0 (patch)
tree95503cad3bea14e88c2030e3764fa3910fdd2d67 /Emby.Server.Implementations
parent5cab79c839d2212ae638db403ec4d7ba0699f9a1 (diff)
parent162c1ac7b7fde0e4929cf262b0f275e3eb15524c (diff)
Merge branch 'master' into embytv
Diffstat (limited to 'Emby.Server.Implementations')
-rw-r--r--Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs15
-rw-r--r--Emby.Server.Implementations/Activity/ActivityManager.cs2
-rw-r--r--Emby.Server.Implementations/Activity/ActivityRepository.cs2
-rw-r--r--Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs26
-rw-r--r--Emby.Server.Implementations/ApplicationHost.cs68
-rw-r--r--Emby.Server.Implementations/Archiving/ZipClient.cs8
-rw-r--r--Emby.Server.Implementations/Branding/BrandingConfigurationFactory.cs2
-rw-r--r--Emby.Server.Implementations/Browser/BrowserLauncher.cs3
-rw-r--r--Emby.Server.Implementations/Channels/ChannelDynamicMediaSourceProvider.cs8
-rw-r--r--Emby.Server.Implementations/Channels/ChannelImageProvider.cs2
-rw-r--r--Emby.Server.Implementations/Channels/ChannelManager.cs12
-rw-r--r--Emby.Server.Implementations/Channels/ChannelPostScanTask.cs2
-rw-r--r--Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs2
-rw-r--r--Emby.Server.Implementations/Collections/CollectionImageProvider.cs3
-rw-r--r--Emby.Server.Implementations/Collections/CollectionManager.cs50
-rw-r--r--Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs30
-rw-r--r--Emby.Server.Implementations/ConfigurationOptions.cs7
-rw-r--r--Emby.Server.Implementations/Cryptography/CryptographyProvider.cs13
-rw-r--r--Emby.Server.Implementations/Data/BaseSqliteRepository.cs6
-rw-r--r--Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs2
-rw-r--r--Emby.Server.Implementations/Data/ManagedConnection.cs2
-rw-r--r--Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs2
-rw-r--r--Emby.Server.Implementations/Data/SqliteExtensions.cs2
-rw-r--r--Emby.Server.Implementations/Data/SqliteItemRepository.cs245
-rw-r--r--Emby.Server.Implementations/Data/SqliteUserDataRepository.cs2
-rw-r--r--Emby.Server.Implementations/Data/SqliteUserRepository.cs2
-rw-r--r--Emby.Server.Implementations/Data/TypeMapper.cs11
-rw-r--r--Emby.Server.Implementations/Devices/DeviceId.cs2
-rw-r--r--Emby.Server.Implementations/Devices/DeviceManager.cs2
-rw-r--r--Emby.Server.Implementations/Diagnostics/CommonProcess.cs2
-rw-r--r--Emby.Server.Implementations/Diagnostics/ProcessFactory.cs2
-rw-r--r--Emby.Server.Implementations/Dto/DtoService.cs2
-rw-r--r--Emby.Server.Implementations/Emby.Server.Implementations.csproj6
-rw-r--r--Emby.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs2
-rw-r--r--Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs2
-rw-r--r--Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs2
-rw-r--r--Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs2
-rw-r--r--Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs37
-rw-r--r--Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs107
-rw-r--r--Emby.Server.Implementations/EntryPoints/StartupWizard.cs21
-rw-r--r--Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs35
-rw-r--r--Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs2
-rw-r--r--Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs1
-rw-r--r--Emby.Server.Implementations/HttpServer/FileWriter.cs2
-rw-r--r--Emby.Server.Implementations/HttpServer/HttpListenerHost.cs2
-rw-r--r--Emby.Server.Implementations/HttpServer/HttpResultFactory.cs8
-rw-r--r--Emby.Server.Implementations/HttpServer/IHttpListener.cs2
-rw-r--r--Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs2
-rw-r--r--Emby.Server.Implementations/HttpServer/ResponseFilter.cs12
-rw-r--r--Emby.Server.Implementations/HttpServer/Security/AuthService.cs2
-rw-r--r--Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs2
-rw-r--r--Emby.Server.Implementations/HttpServer/Security/SessionContext.cs2
-rw-r--r--Emby.Server.Implementations/HttpServer/StreamWriter.cs57
-rw-r--r--Emby.Server.Implementations/HttpServer/WebSocketConnection.cs110
-rw-r--r--Emby.Server.Implementations/IO/ExtendedFileSystemInfo.cs2
-rw-r--r--Emby.Server.Implementations/IO/FileRefresher.cs2
-rw-r--r--Emby.Server.Implementations/IO/LibraryMonitor.cs10
-rw-r--r--Emby.Server.Implementations/IO/ManagedFileSystem.cs4
-rw-r--r--Emby.Server.Implementations/IO/MbLinkShortcutHandler.cs2
-rw-r--r--Emby.Server.Implementations/IO/StreamHelper.cs2
-rw-r--r--Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs2
-rw-r--r--Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs4
-rw-r--r--Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs10
-rw-r--r--Emby.Server.Implementations/Library/DefaultPasswordResetProvider.cs13
-rw-r--r--Emby.Server.Implementations/Library/ExclusiveLiveStream.cs2
-rw-r--r--Emby.Server.Implementations/Library/InvalidAuthProvider.cs11
-rw-r--r--Emby.Server.Implementations/Library/LibraryManager.cs10
-rw-r--r--Emby.Server.Implementations/Library/LiveStreamHelper.cs2
-rw-r--r--Emby.Server.Implementations/Library/MediaSourceManager.cs17
-rw-r--r--Emby.Server.Implementations/Library/MediaStreamSelector.cs2
-rw-r--r--Emby.Server.Implementations/Library/MusicManager.cs5
-rw-r--r--Emby.Server.Implementations/Library/PathExtensions.cs4
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs4
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs35
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs15
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs4
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs15
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/FolderResolver.cs4
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs2
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs5
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs10
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs10
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs2
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs3
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs2
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs7
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs10
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs2
-rw-r--r--Emby.Server.Implementations/Library/SearchEngine.cs6
-rw-r--r--Emby.Server.Implementations/Library/UserDataManager.cs18
-rw-r--r--Emby.Server.Implementations/Library/UserManager.cs120
-rw-r--r--Emby.Server.Implementations/Library/UserViewManager.cs4
-rw-r--r--Emby.Server.Implementations/Library/Validators/ArtistsPostScanTask.cs6
-rw-r--r--Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs6
-rw-r--r--Emby.Server.Implementations/Library/Validators/GenresPostScanTask.cs3
-rw-r--r--Emby.Server.Implementations/Library/Validators/GenresValidator.cs15
-rw-r--r--Emby.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs4
-rw-r--r--Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs15
-rw-r--r--Emby.Server.Implementations/Library/Validators/PeopleValidator.cs1
-rw-r--r--Emby.Server.Implementations/Library/Validators/StudiosPostScanTask.cs6
-rw-r--r--Emby.Server.Implementations/Library/Validators/StudiosValidator.cs16
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs19
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs6
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs4
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvManager.cs31
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs3
-rw-r--r--Emby.Server.Implementations/Localization/Core/af.json96
-rw-r--r--Emby.Server.Implementations/Localization/Core/bg-BG.json4
-rw-r--r--Emby.Server.Implementations/Localization/Core/ca.json74
-rw-r--r--Emby.Server.Implementations/Localization/Core/de.json4
-rw-r--r--Emby.Server.Implementations/Localization/Core/el.json2
-rw-r--r--Emby.Server.Implementations/Localization/Core/fr.json4
-rw-r--r--Emby.Server.Implementations/Localization/Core/he.json60
-rw-r--r--Emby.Server.Implementations/Localization/Core/id.json32
-rw-r--r--Emby.Server.Implementations/Localization/Core/is.json78
-rw-r--r--Emby.Server.Implementations/Localization/Core/it.json14
-rw-r--r--Emby.Server.Implementations/Localization/Core/ko.json8
-rw-r--r--Emby.Server.Implementations/Localization/Core/lt-LT.json150
-rw-r--r--Emby.Server.Implementations/Localization/Core/nb.json54
-rw-r--r--Emby.Server.Implementations/Localization/Core/nl.json6
-rw-r--r--Emby.Server.Implementations/Localization/Core/pt-BR.json24
-rw-r--r--Emby.Server.Implementations/Localization/Core/pt.json96
-rw-r--r--Emby.Server.Implementations/Localization/Core/ro.json96
-rw-r--r--Emby.Server.Implementations/Localization/Core/ru.json6
-rw-r--r--Emby.Server.Implementations/Localization/Core/sk.json40
-rw-r--r--Emby.Server.Implementations/Localization/Core/sv.json16
-rw-r--r--Emby.Server.Implementations/Localization/Core/tr.json64
-rw-r--r--Emby.Server.Implementations/Localization/Core/zh-CN.json6
-rw-r--r--Emby.Server.Implementations/Localization/Core/zh-HK.json2
-rw-r--r--Emby.Server.Implementations/Localization/Core/zh-TW.json2
-rw-r--r--Emby.Server.Implementations/Networking/NetworkManager.cs40
-rw-r--r--Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs5
-rw-r--r--Emby.Server.Implementations/Playlists/PlaylistManager.cs35
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs7
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs4
-rw-r--r--Emby.Server.Implementations/ServerApplicationPaths.cs17
-rw-r--r--Emby.Server.Implementations/Session/SessionManager.cs71
-rw-r--r--Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs45
-rw-r--r--Emby.Server.Implementations/Updates/InstallationManager.cs23
-rw-r--r--Emby.Server.Implementations/UserViews/DynamicImageProvider.cs5
140 files changed, 1785 insertions, 879 deletions
diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs
index efaaa116c..b622a3167 100644
--- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs
+++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -39,6 +41,19 @@ namespace Emby.Server.Implementations.Activity
private readonly IServerApplicationHost _appHost;
private readonly IDeviceManager _deviceManager;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ActivityLogEntryPoint"/> class.
+ /// </summary>
+ /// <param name="logger"></param>
+ /// <param name="sessionManager"></param>
+ /// <param name="deviceManager"></param>
+ /// <param name="taskManager"></param>
+ /// <param name="activityManager"></param>
+ /// <param name="localization"></param>
+ /// <param name="installationManager"></param>
+ /// <param name="subManager"></param>
+ /// <param name="userManager"></param>
+ /// <param name="appHost"></param>
public ActivityLogEntryPoint(
ILogger<ActivityLogEntryPoint> logger,
ISessionManager sessionManager,
diff --git a/Emby.Server.Implementations/Activity/ActivityManager.cs b/Emby.Server.Implementations/Activity/ActivityManager.cs
index 0c513ea12..a30e93912 100644
--- a/Emby.Server.Implementations/Activity/ActivityManager.cs
+++ b/Emby.Server.Implementations/Activity/ActivityManager.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Linq;
using MediaBrowser.Controller.Library;
diff --git a/Emby.Server.Implementations/Activity/ActivityRepository.cs b/Emby.Server.Implementations/Activity/ActivityRepository.cs
index ffaeaa541..7be72319e 100644
--- a/Emby.Server.Implementations/Activity/ActivityRepository.cs
+++ b/Emby.Server.Implementations/Activity/ActivityRepository.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Globalization;
diff --git a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs
index 67bb25b07..080cfbbd1 100644
--- a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs
+++ b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs
@@ -84,6 +84,7 @@ namespace Emby.Server.Implementations.AppBase
/// </summary>
/// <value>The logger.</value>
protected ILogger Logger { get; private set; }
+
/// <summary>
/// Gets the XML serializer.
/// </summary>
@@ -97,7 +98,7 @@ namespace Emby.Server.Implementations.AppBase
public IApplicationPaths CommonApplicationPaths { get; private set; }
/// <summary>
- /// Gets the system configuration.
+ /// Gets or sets the system configuration.
/// </summary>
/// <value>The configuration.</value>
public BaseApplicationConfiguration CommonConfiguration
@@ -123,6 +124,7 @@ namespace Emby.Server.Implementations.AppBase
return _configuration;
}
}
+
protected set
{
_configuration = value;
@@ -131,6 +133,10 @@ namespace Emby.Server.Implementations.AppBase
}
}
+ /// <summary>
+ /// Adds parts.
+ /// </summary>
+ /// <param name="factories">The configuration factories.</param>
public virtual void AddParts(IEnumerable<IConfigurationFactory> factories)
{
_configurationFactories = factories.ToArray();
@@ -215,7 +221,7 @@ namespace Emby.Server.Implementations.AppBase
cachePath = CommonConfiguration.CachePath;
}
- Logger.LogInformation("Setting cache path to " + cachePath);
+ Logger.LogInformation("Setting cache path: {Path}", cachePath);
((BaseApplicationPaths)CommonApplicationPaths).CachePath = cachePath;
}
@@ -223,7 +229,7 @@ namespace Emby.Server.Implementations.AppBase
/// Replaces the cache path.
/// </summary>
/// <param name="newConfig">The new configuration.</param>
- /// <exception cref="DirectoryNotFoundException"></exception>
+ /// <exception cref="DirectoryNotFoundException">The new cache path doesn't exist.</exception>
private void ValidateCachePath(BaseApplicationConfiguration newConfig)
{
var newPath = newConfig.CachePath;
@@ -234,7 +240,7 @@ namespace Emby.Server.Implementations.AppBase
// Validate
if (!Directory.Exists(newPath))
{
- throw new FileNotFoundException(
+ throw new DirectoryNotFoundException(
string.Format(
CultureInfo.InvariantCulture,
"{0} does not exist.",
@@ -245,6 +251,10 @@ namespace Emby.Server.Implementations.AppBase
}
}
+ /// <summary>
+ /// Ensures that we have write access to the path.
+ /// </summary>
+ /// <param name="path">The path.</param>
protected void EnsureWriteAccess(string path)
{
var file = Path.Combine(path, Guid.NewGuid().ToString());
@@ -257,6 +267,7 @@ namespace Emby.Server.Implementations.AppBase
return Path.Combine(CommonApplicationPaths.ConfigurationDirectoryPath, key.ToLowerInvariant() + ".xml");
}
+ /// <inheritdoc />
public object GetConfiguration(string key)
{
return _configurations.GetOrAdd(key, k =>
@@ -303,6 +314,7 @@ namespace Emby.Server.Implementations.AppBase
}
}
+ /// <inheritdoc />
public void SaveConfiguration(string key, object configuration)
{
var configurationStore = GetConfigurationStore(key);
@@ -339,6 +351,11 @@ namespace Emby.Server.Implementations.AppBase
OnNamedConfigurationUpdated(key, configuration);
}
+ /// <summary>
+ /// Event handler for when a named configuration has been updated.
+ /// </summary>
+ /// <param name="key">The key of the configuration.</param>
+ /// <param name="configuration">The old configuration.</param>
protected virtual void OnNamedConfigurationUpdated(string key, object configuration)
{
NamedConfigurationUpdated?.Invoke(this, new ConfigurationUpdateEventArgs
@@ -348,6 +365,7 @@ namespace Emby.Server.Implementations.AppBase
});
}
+ /// <inheritdoc />
public Type GetConfigurationType(string key)
{
return GetConfigurationStore(key)
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index 8c625539a..a179c1b15 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -103,14 +103,11 @@ using MediaBrowser.Providers.Subtitles;
using MediaBrowser.Providers.TV.TheTVDB;
using MediaBrowser.WebDashboard.Api;
using MediaBrowser.XbmcMetadata.Providers;
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
-using Microsoft.OpenApi.Models;
using OperatingSystem = MediaBrowser.Common.System.OperatingSystem;
namespace Emby.Server.Implementations
@@ -764,9 +761,8 @@ namespace Emby.Server.Implementations
LibraryManager = new LibraryManager(this, LoggerFactory, TaskManager, UserManager, ServerConfigurationManager, UserDataManager, () => LibraryMonitor, FileSystemManager, () => ProviderManager, () => UserViewManager);
serviceCollection.AddSingleton(LibraryManager);
- // TODO wtaylor: investigate use of second music manager
var musicManager = new MusicManager(LibraryManager);
- serviceCollection.AddSingleton<IMusicManager>(new MusicManager(LibraryManager));
+ serviceCollection.AddSingleton<IMusicManager>(musicManager);
LibraryMonitor = new LibraryMonitor(LoggerFactory, LibraryManager, ServerConfigurationManager, FileSystemManager);
serviceCollection.AddSingleton(LibraryMonitor);
@@ -841,16 +837,14 @@ namespace Emby.Server.Implementations
serviceCollection.AddSingleton(ChapterManager);
MediaEncoder = new MediaBrowser.MediaEncoding.Encoder.MediaEncoder(
- LoggerFactory,
- JsonSerializer,
- StartupOptions.FFmpegPath,
+ LoggerFactory.CreateLogger<MediaBrowser.MediaEncoding.Encoder.MediaEncoder>(),
ServerConfigurationManager,
FileSystemManager,
- () => SubtitleEncoder,
- () => MediaSourceManager,
ProcessFactory,
- 5000,
- LocalizationManager);
+ LocalizationManager,
+ () => SubtitleEncoder,
+ _configuration,
+ StartupOptions.FFmpegPath);
serviceCollection.AddSingleton(MediaEncoder);
EncodingManager = new MediaEncoder.EncodingManager(FileSystemManager, LoggerFactory, MediaEncoder, ChapterManager, LibraryManager);
@@ -867,10 +861,21 @@ namespace Emby.Server.Implementations
AuthService = new AuthService(LoggerFactory.CreateLogger<AuthService>(), authContext, ServerConfigurationManager, SessionManager, NetworkManager);
serviceCollection.AddSingleton(AuthService);
- SubtitleEncoder = new MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder(LibraryManager, LoggerFactory, ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer, HttpClient, MediaSourceManager, ProcessFactory);
+ SubtitleEncoder = new MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder(
+ LibraryManager,
+ LoggerFactory.CreateLogger<MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder>(),
+ ApplicationPaths,
+ FileSystemManager,
+ MediaEncoder,
+ HttpClient,
+ MediaSourceManager,
+ ProcessFactory);
serviceCollection.AddSingleton(SubtitleEncoder);
serviceCollection.AddSingleton(typeof(IResourceFileManager), typeof(ResourceFileManager));
+ serviceCollection.AddSingleton<EncodingHelper>();
+
+ serviceCollection.AddSingleton(typeof(IAttachmentExtractor), typeof(MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor));
_displayPreferencesRepository.Initialize();
@@ -1472,7 +1477,7 @@ namespace Emby.Server.Implementations
/// </summary>
/// <param name="address">The IPv6 address.</param>
/// <returns>The IPv6 address without the scope id.</returns>
- private string RemoveScopeId(string address)
+ private ReadOnlySpan<char> RemoveScopeId(ReadOnlySpan<char> address)
{
var index = address.IndexOf('%');
if (index == -1)
@@ -1480,33 +1485,50 @@ namespace Emby.Server.Implementations
return address;
}
- return address.Substring(0, index);
+ return address.Slice(0, index);
}
+ /// <inheritdoc />
public string GetLocalApiUrl(IPAddress ipAddress)
{
if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
{
var str = RemoveScopeId(ipAddress.ToString());
+ Span<char> span = new char[str.Length + 2];
+ span[0] = '[';
+ str.CopyTo(span.Slice(1));
+ span[^1] = ']';
- return GetLocalApiUrl("[" + str + "]");
+ return GetLocalApiUrl(span);
}
return GetLocalApiUrl(ipAddress.ToString());
}
- public string GetLocalApiUrl(string host)
+ /// <inheritdoc />
+ public string GetLocalApiUrl(ReadOnlySpan<char> host)
{
+ var url = new StringBuilder(64);
if (EnableHttps)
{
- return string.Format("https://{0}:{1}",
- host,
- HttpsPort.ToString(CultureInfo.InvariantCulture));
+ url.Append("https://");
+ }
+ else
+ {
+ url.Append("http://");
+ }
+
+ url.Append(host)
+ .Append(':')
+ .Append(HttpPort);
+
+ string baseUrl = ServerConfigurationManager.Configuration.BaseUrl;
+ if (baseUrl.Length != 0)
+ {
+ url.Append('/').Append(baseUrl);
}
- return string.Format("http://{0}:{1}",
- host,
- HttpPort.ToString(CultureInfo.InvariantCulture));
+ return url.ToString();
}
public Task<List<IPAddress>> GetLocalIpAddresses(CancellationToken cancellationToken)
diff --git a/Emby.Server.Implementations/Archiving/ZipClient.cs b/Emby.Server.Implementations/Archiving/ZipClient.cs
index 6b0fd2dc6..4a6e5cfd7 100644
--- a/Emby.Server.Implementations/Archiving/ZipClient.cs
+++ b/Emby.Server.Implementations/Archiving/ZipClient.cs
@@ -10,15 +10,10 @@ using SharpCompress.Readers.Zip;
namespace Emby.Server.Implementations.Archiving
{
/// <summary>
- /// Class DotNetZipClient
+ /// Class DotNetZipClient.
/// </summary>
public class ZipClient : IZipClient
{
- public ZipClient()
- {
-
- }
-
/// <summary>
/// Extracts all.
/// </summary>
@@ -144,7 +139,6 @@ namespace Emby.Server.Implementations.Archiving
}
}
-
/// <summary>
/// Extracts all from tar.
/// </summary>
diff --git a/Emby.Server.Implementations/Branding/BrandingConfigurationFactory.cs b/Emby.Server.Implementations/Branding/BrandingConfigurationFactory.cs
index b27f84848..93000ae12 100644
--- a/Emby.Server.Implementations/Branding/BrandingConfigurationFactory.cs
+++ b/Emby.Server.Implementations/Branding/BrandingConfigurationFactory.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System.Collections.Generic;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Model.Branding;
diff --git a/Emby.Server.Implementations/Browser/BrowserLauncher.cs b/Emby.Server.Implementations/Browser/BrowserLauncher.cs
index 718129ef0..f5da0d018 100644
--- a/Emby.Server.Implementations/Browser/BrowserLauncher.cs
+++ b/Emby.Server.Implementations/Browser/BrowserLauncher.cs
@@ -4,7 +4,7 @@ using MediaBrowser.Controller;
namespace Emby.Server.Implementations.Browser
{
/// <summary>
- /// Class BrowserLauncher
+ /// Class BrowserLauncher.
/// </summary>
public static class BrowserLauncher
{
@@ -32,6 +32,7 @@ namespace Emby.Server.Implementations.Browser
/// <summary>
/// Opens the URL.
/// </summary>
+ /// <param name="appHost">The application host instance.</param>
/// <param name="url">The URL.</param>
private static void OpenUrl(IServerApplicationHost appHost, string url)
{
diff --git a/Emby.Server.Implementations/Channels/ChannelDynamicMediaSourceProvider.cs b/Emby.Server.Implementations/Channels/ChannelDynamicMediaSourceProvider.cs
index c10f00f9b..6016fed07 100644
--- a/Emby.Server.Implementations/Channels/ChannelDynamicMediaSourceProvider.cs
+++ b/Emby.Server.Implementations/Channels/ChannelDynamicMediaSourceProvider.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Threading;
@@ -13,11 +15,16 @@ namespace Emby.Server.Implementations.Channels
{
private readonly ChannelManager _channelManager;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ChannelDynamicMediaSourceProvider"/> class.
+ /// </summary>
+ /// <param name="channelManager">The channel manager.</param>
public ChannelDynamicMediaSourceProvider(IChannelManager channelManager)
{
_channelManager = (ChannelManager)channelManager;
}
+ /// <inheritdoc />
public Task<IEnumerable<MediaSourceInfo>> GetMediaSources(BaseItem item, CancellationToken cancellationToken)
{
if (item.SourceType == SourceType.Channel)
@@ -28,6 +35,7 @@ namespace Emby.Server.Implementations.Channels
return Task.FromResult<IEnumerable<MediaSourceInfo>>(new List<MediaSourceInfo>());
}
+ /// <inheritdoc />
public Task<ILiveStream> OpenMediaSource(string openToken, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken)
{
throw new NotImplementedException();
diff --git a/Emby.Server.Implementations/Channels/ChannelImageProvider.cs b/Emby.Server.Implementations/Channels/ChannelImageProvider.cs
index bafa68818..62aeb9bcb 100644
--- a/Emby.Server.Implementations/Channels/ChannelImageProvider.cs
+++ b/Emby.Server.Implementations/Channels/ChannelImageProvider.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System.Collections.Generic;
using System.Linq;
using System.Threading;
diff --git a/Emby.Server.Implementations/Channels/ChannelManager.cs b/Emby.Server.Implementations/Channels/ChannelManager.cs
index 151670074..6e1baddfe 100644
--- a/Emby.Server.Implementations/Channels/ChannelManager.cs
+++ b/Emby.Server.Implementations/Channels/ChannelManager.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -510,7 +512,7 @@ namespace Emby.Server.Implementations.Channels
return _libraryManager.GetItemIds(new InternalItemsQuery
{
IncludeItemTypes = new[] { typeof(Channel).Name },
- OrderBy = new ValueTuple<string, SortOrder>[] { new ValueTuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending) }
+ OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) }
}).Select(i => GetChannelFeatures(i.ToString("N", CultureInfo.InvariantCulture))).ToArray();
}
@@ -618,16 +620,16 @@ namespace Emby.Server.Implementations.Channels
{
query.OrderBy = new[]
{
- new ValueTuple<string, SortOrder>(ItemSortBy.PremiereDate, SortOrder.Descending),
- new ValueTuple<string, SortOrder>(ItemSortBy.ProductionYear, SortOrder.Descending),
- new ValueTuple<string, SortOrder>(ItemSortBy.DateCreated, SortOrder.Descending)
+ (ItemSortBy.PremiereDate, SortOrder.Descending),
+ (ItemSortBy.ProductionYear, SortOrder.Descending),
+ (ItemSortBy.DateCreated, SortOrder.Descending)
};
}
else
{
query.OrderBy = new[]
{
- new ValueTuple<string, SortOrder>(ItemSortBy.DateCreated, SortOrder.Descending)
+ (ItemSortBy.DateCreated, SortOrder.Descending)
};
}
diff --git a/Emby.Server.Implementations/Channels/ChannelPostScanTask.cs b/Emby.Server.Implementations/Channels/ChannelPostScanTask.cs
index 3c7cbb115..2712fc8c5 100644
--- a/Emby.Server.Implementations/Channels/ChannelPostScanTask.cs
+++ b/Emby.Server.Implementations/Channels/ChannelPostScanTask.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Linq;
using System.Threading;
diff --git a/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs b/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs
index 303a8ac7b..5774c0415 100644
--- a/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs
+++ b/Emby.Server.Implementations/Channels/RefreshChannelsScheduledTask.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Threading;
diff --git a/Emby.Server.Implementations/Collections/CollectionImageProvider.cs b/Emby.Server.Implementations/Collections/CollectionImageProvider.cs
index 0244c4a68..1fa556ec9 100644
--- a/Emby.Server.Implementations/Collections/CollectionImageProvider.cs
+++ b/Emby.Server.Implementations/Collections/CollectionImageProvider.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Linq;
@@ -76,7 +78,6 @@ namespace Emby.Server.Implementations.Collections
.Where(i => i != null)
.GroupBy(x => x.Id)
.Select(x => x.First())
- .OrderBy(i => Guid.NewGuid())
.ToList();
}
diff --git a/Emby.Server.Implementations/Collections/CollectionManager.cs b/Emby.Server.Implementations/Collections/CollectionManager.cs
index c5a77ce5b..1d7c11989 100644
--- a/Emby.Server.Implementations/Collections/CollectionManager.cs
+++ b/Emby.Server.Implementations/Collections/CollectionManager.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -29,11 +31,7 @@ namespace Emby.Server.Implementations.Collections
private readonly ILogger _logger;
private readonly IProviderManager _providerManager;
private readonly ILocalizationManager _localizationManager;
- private IApplicationPaths _appPaths;
-
- public event EventHandler<CollectionCreatedEventArgs> CollectionCreated;
- public event EventHandler<CollectionModifiedEventArgs> ItemsAddedToCollection;
- public event EventHandler<CollectionModifiedEventArgs> ItemsRemovedFromCollection;
+ private readonly IApplicationPaths _appPaths;
public CollectionManager(
ILibraryManager libraryManager,
@@ -53,6 +51,10 @@ namespace Emby.Server.Implementations.Collections
_appPaths = appPaths;
}
+ public event EventHandler<CollectionCreatedEventArgs> CollectionCreated;
+ public event EventHandler<CollectionModifiedEventArgs> ItemsAddedToCollection;
+ public event EventHandler<CollectionModifiedEventArgs> ItemsRemovedFromCollection;
+
private IEnumerable<Folder> FindFolders(string path)
{
return _libraryManager
@@ -339,11 +341,11 @@ namespace Emby.Server.Implementations.Collections
}
}
- public class CollectionManagerEntryPoint : IServerEntryPoint
+ public sealed class CollectionManagerEntryPoint : IServerEntryPoint
{
private readonly CollectionManager _collectionManager;
private readonly IServerConfigurationManager _config;
- private ILogger _logger;
+ private readonly ILogger _logger;
public CollectionManagerEntryPoint(ICollectionManager collectionManager, IServerConfigurationManager config, ILogger logger)
{
@@ -352,6 +354,7 @@ namespace Emby.Server.Implementations.Collections
_logger = logger;
}
+ /// <inheritdoc />
public async Task RunAsync()
{
if (!_config.Configuration.CollectionsUpgraded && _config.Configuration.IsStartupWizardCompleted)
@@ -375,39 +378,10 @@ namespace Emby.Server.Implementations.Collections
}
}
- #region IDisposable Support
- private bool disposedValue = false; // To detect redundant calls
-
- protected virtual void Dispose(bool disposing)
- {
- if (!disposedValue)
- {
- if (disposing)
- {
- // TODO: dispose managed state (managed objects).
- }
-
- // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
- // TODO: set large fields to null.
-
- disposedValue = true;
- }
- }
-
- // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
- // ~CollectionManagerEntryPoint() {
- // // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
- // Dispose(false);
- // }
-
- // This code added to correctly implement the disposable pattern.
+ /// <inheritdoc />
public void Dispose()
{
- // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
- Dispose(true);
- // TODO: uncomment the following line if the finalizer is overridden above.
- // GC.SuppressFinalize(this);
+ // Nothing to dispose
}
- #endregion
}
}
diff --git a/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs b/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs
index 2291345be..3d8d15d19 100644
--- a/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs
+++ b/Emby.Server.Implementations/Configuration/ServerConfigurationManager.cs
@@ -1,4 +1,6 @@
using System;
+using System.Collections.Generic;
+using System.Globalization;
using System.IO;
using Emby.Server.Implementations.AppBase;
using MediaBrowser.Common.Configuration;
@@ -17,7 +19,6 @@ namespace Emby.Server.Implementations.Configuration
/// </summary>
public class ServerConfigurationManager : BaseConfigurationManager, IServerConfigurationManager
{
-
/// <summary>
/// Initializes a new instance of the <see cref="ServerConfigurationManager" /> class.
/// </summary>
@@ -31,6 +32,9 @@ namespace Emby.Server.Implementations.Configuration
UpdateMetadataPath();
}
+ /// <summary>
+ /// Configuration updating event.
+ /// </summary>
public event EventHandler<GenericEventArgs<ServerConfiguration>> ConfigurationUpdating;
/// <summary>
@@ -97,7 +101,7 @@ namespace Emby.Server.Implementations.Configuration
/// Validates the SSL certificate.
/// </summary>
/// <param name="newConfig">The new configuration.</param>
- /// <exception cref="DirectoryNotFoundException"></exception>
+ /// <exception cref="FileNotFoundException">The certificate path doesn't exist.</exception>
private void ValidateSslCertificate(BaseApplicationConfiguration newConfig)
{
var serverConfig = (ServerConfiguration)newConfig;
@@ -105,12 +109,16 @@ namespace Emby.Server.Implementations.Configuration
var newPath = serverConfig.CertificatePath;
if (!string.IsNullOrWhiteSpace(newPath)
- && !string.Equals(Configuration.CertificatePath ?? string.Empty, newPath))
+ && !string.Equals(Configuration.CertificatePath, newPath, StringComparison.Ordinal))
{
// Validate
if (!File.Exists(newPath))
{
- throw new FileNotFoundException(string.Format("Certificate file '{0}' does not exist.", newPath));
+ throw new FileNotFoundException(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "Certificate file '{0}' does not exist.",
+ newPath));
}
}
}
@@ -119,24 +127,32 @@ namespace Emby.Server.Implementations.Configuration
/// Validates the metadata path.
/// </summary>
/// <param name="newConfig">The new configuration.</param>
- /// <exception cref="DirectoryNotFoundException"></exception>
+ /// <exception cref="DirectoryNotFoundException">The new config path doesn't exist.</exception>
private void ValidateMetadataPath(ServerConfiguration newConfig)
{
var newPath = newConfig.MetadataPath;
if (!string.IsNullOrWhiteSpace(newPath)
- && !string.Equals(Configuration.MetadataPath ?? string.Empty, newPath))
+ && !string.Equals(Configuration.MetadataPath, newPath, StringComparison.Ordinal))
{
// Validate
if (!Directory.Exists(newPath))
{
- throw new FileNotFoundException(string.Format("{0} does not exist.", newPath));
+ throw new DirectoryNotFoundException(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "{0} does not exist.",
+ newPath));
}
EnsureWriteAccess(newPath);
}
}
+ /// <summary>
+ /// Sets all configuration values to their optimal values.
+ /// </summary>
+ /// <returns>If the configuration changed.</returns>
public bool SetOptimalValues()
{
var config = Configuration;
diff --git a/Emby.Server.Implementations/ConfigurationOptions.cs b/Emby.Server.Implementations/ConfigurationOptions.cs
index 62408ee70..2ea7ff6e9 100644
--- a/Emby.Server.Implementations/ConfigurationOptions.cs
+++ b/Emby.Server.Implementations/ConfigurationOptions.cs
@@ -1,13 +1,16 @@
using System.Collections.Generic;
+using static MediaBrowser.Controller.Extensions.ConfigurationExtensions;
namespace Emby.Server.Implementations
{
public static class ConfigurationOptions
{
- public static readonly Dictionary<string, string> Configuration = new Dictionary<string, string>
+ public static Dictionary<string, string> Configuration => new Dictionary<string, string>
{
{ "HttpListenerHost:DefaultRedirectPath", "web/index.html" },
- { "MusicBrainz:BaseUrl", "https://www.musicbrainz.org" }
+ { "MusicBrainz:BaseUrl", "https://www.musicbrainz.org" },
+ { FfmpegProbeSizeKey, "1G" },
+ { FfmpegAnalyzeDurationKey, "200M" }
};
}
}
diff --git a/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs b/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs
index fec7d161e..776074b72 100644
--- a/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs
+++ b/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs
@@ -6,6 +6,9 @@ using static MediaBrowser.Common.Cryptography.Constants;
namespace Emby.Server.Implementations.Cryptography
{
+ /// <summary>
+ /// Class providing abstractions over cryptographic functions.
+ /// </summary>
public class CryptographyProvider : ICryptoProvider, IDisposable
{
private static readonly HashSet<string> _supportedHashMethods = new HashSet<string>()
@@ -42,8 +45,10 @@ namespace Emby.Server.Implementations.Cryptography
_randomNumberGenerator = RandomNumberGenerator.Create();
}
+ /// <inheritdoc />
public string DefaultHashMethod => "PBKDF2";
+ /// <inheritdoc />
public IEnumerable<string> GetSupportedHashMethods()
=> _supportedHashMethods;
@@ -62,6 +67,7 @@ namespace Emby.Server.Implementations.Cryptography
throw new CryptographicException($"Cannot currently use PBKDF2 with requested hash method: {method}");
}
+ /// <inheritdoc />
public byte[] ComputeHash(string hashMethod, byte[] bytes, byte[] salt)
{
if (hashMethod == DefaultHashMethod)
@@ -89,12 +95,15 @@ namespace Emby.Server.Implementations.Cryptography
throw new CryptographicException($"Requested hash method is not supported: {hashMethod}");
}
+ /// <inheritdoc />
public byte[] ComputeHashWithDefaultMethod(byte[] bytes, byte[] salt)
=> PBKDF2(DefaultHashMethod, bytes, salt, DefaultIterations);
+ /// <inheritdoc />
public byte[] GenerateSalt()
=> GenerateSalt(DefaultSaltLength);
+ /// <inheritdoc />
public byte[] GenerateSalt(int length)
{
byte[] salt = new byte[length];
@@ -109,6 +118,10 @@ namespace Emby.Server.Implementations.Cryptography
GC.SuppressFinalize(this);
}
+ /// <summary>
+ /// Releases unmanaged and - optionally - managed resources.
+ /// </summary>
+ /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{
if (_disposed)
diff --git a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs
index 4e392f6c9..0654132f4 100644
--- a/Emby.Server.Implementations/Data/BaseSqliteRepository.cs
+++ b/Emby.Server.Implementations/Data/BaseSqliteRepository.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Linq;
@@ -11,6 +13,10 @@ namespace Emby.Server.Implementations.Data
{
private bool _disposed = false;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="BaseSqliteRepository"/> class.
+ /// </summary>
+ /// <param name="logger">The logger.</param>
protected BaseSqliteRepository(ILogger logger)
{
Logger = logger;
diff --git a/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs b/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs
index f7743a3c2..2a8f2d6b3 100644
--- a/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs
+++ b/Emby.Server.Implementations/Data/CleanDatabaseScheduledTask.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Threading;
using System.Threading.Tasks;
diff --git a/Emby.Server.Implementations/Data/ManagedConnection.cs b/Emby.Server.Implementations/Data/ManagedConnection.cs
index 4c3424410..5c094ddd2 100644
--- a/Emby.Server.Implementations/Data/ManagedConnection.cs
+++ b/Emby.Server.Implementations/Data/ManagedConnection.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Threading;
diff --git a/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs b/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs
index 2f6c1288d..d474f1c6b 100644
--- a/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteDisplayPreferencesRepository.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Globalization;
diff --git a/Emby.Server.Implementations/Data/SqliteExtensions.cs b/Emby.Server.Implementations/Data/SqliteExtensions.cs
index c76ae0cac..c87793072 100644
--- a/Emby.Server.Implementations/Data/SqliteExtensions.cs
+++ b/Emby.Server.Implementations/Data/SqliteExtensions.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Globalization;
diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
index 8d509f688..c514846e5 100644
--- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
@@ -7,6 +7,7 @@ using System.Text;
using System.Text.Json;
using System.Threading;
using Emby.Server.Implementations.Playlists;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Json;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Channels;
@@ -48,6 +49,21 @@ namespace Emby.Server.Implementations.Data
private readonly TypeMapper _typeMapper;
private readonly JsonSerializerOptions _jsonOptions;
+ static SqliteItemRepository()
+ {
+ var queryPrefixText = new StringBuilder();
+ queryPrefixText.Append("insert into mediaattachments (");
+ foreach (var column in _mediaAttachmentSaveColumns)
+ {
+ queryPrefixText.Append(column)
+ .Append(',');
+ }
+
+ queryPrefixText.Length -= 1;
+ queryPrefixText.Append(") values ");
+ _mediaAttachmentInsertPrefix = queryPrefixText.ToString();
+ }
+
/// <summary>
/// Initializes a new instance of the <see cref="SqliteItemRepository"/> class.
/// </summary>
@@ -91,6 +107,8 @@ namespace Emby.Server.Implementations.Data
{
const string CreateMediaStreamsTableCommand
= "create table if not exists mediastreams (ItemId GUID, StreamIndex INT, StreamType TEXT, Codec TEXT, Language TEXT, ChannelLayout TEXT, Profile TEXT, AspectRatio TEXT, Path TEXT, IsInterlaced BIT, BitRate INT NULL, Channels INT NULL, SampleRate INT NULL, IsDefault BIT, IsForced BIT, IsExternal BIT, Height INT NULL, Width INT NULL, AverageFrameRate FLOAT NULL, RealFrameRate FLOAT NULL, Level FLOAT NULL, PixelFormat TEXT, BitDepth INT NULL, IsAnamorphic BIT NULL, RefFrames INT NULL, CodecTag TEXT NULL, Comment TEXT NULL, NalLengthSize TEXT NULL, IsAvc BIT NULL, Title TEXT NULL, TimeBase TEXT NULL, CodecTimeBase TEXT NULL, ColorPrimaries TEXT NULL, ColorSpace TEXT NULL, ColorTransfer TEXT NULL, PRIMARY KEY (ItemId, StreamIndex))";
+ const string CreateMediaAttachmentsTableCommand
+ = "create table if not exists mediaattachments (ItemId GUID, AttachmentIndex INT, Codec TEXT, CodecTag TEXT NULL, Comment TEXT NULL, Filename TEXT NULL, MIMEType TEXT NULL, PRIMARY KEY (ItemId, AttachmentIndex))";
string[] queries =
{
@@ -113,6 +131,7 @@ namespace Emby.Server.Implementations.Data
"create table if not exists " + ChaptersTableName + " (ItemId GUID, ChapterIndex INT NOT NULL, StartPositionTicks BIGINT NOT NULL, Name TEXT, ImagePath TEXT, PRIMARY KEY (ItemId, ChapterIndex))",
CreateMediaStreamsTableCommand,
+ CreateMediaAttachmentsTableCommand,
"pragma shrink_memory"
};
@@ -420,6 +439,19 @@ namespace Emby.Server.Implementations.Data
"ColorTransfer"
};
+ private static readonly string[] _mediaAttachmentSaveColumns =
+ {
+ "ItemId",
+ "AttachmentIndex",
+ "Codec",
+ "CodecTag",
+ "Comment",
+ "Filename",
+ "MIMEType"
+ };
+
+ private static readonly string _mediaAttachmentInsertPrefix;
+
private static string GetSaveItemCommandText()
{
var saveColumns = new []
@@ -2831,8 +2863,8 @@ namespace Emby.Server.Implementations.Data
BindSimilarParams(query, statement);
BindSearchParams(query, statement);
- // Running this again will bind the params
- GetWhereClauses(query, statement);
+ // Running this again will bind the params
+ GetWhereClauses(query, statement);
var hasEpisodeAttributes = HasEpisodeAttributes(query);
var hasServiceName = HasServiceName(query);
@@ -2881,14 +2913,14 @@ namespace Emby.Server.Implementations.Data
private string GetOrderByText(InternalItemsQuery query)
{
+ var orderBy = query.OrderBy;
if (string.IsNullOrEmpty(query.SearchTerm))
{
- int oldLen = query.OrderBy.Length;
-
- if (query.SimilarTo != null && oldLen == 0)
+ int oldLen = orderBy.Count;
+ if (oldLen == 0 && query.SimilarTo != null)
{
var arr = new (string, SortOrder)[oldLen + 2];
- query.OrderBy.CopyTo(arr, 0);
+ orderBy.CopyTo(arr, 0);
arr[oldLen] = ("SimilarityScore", SortOrder.Descending);
arr[oldLen + 1] = (ItemSortBy.Random, SortOrder.Ascending);
query.OrderBy = arr;
@@ -2896,16 +2928,15 @@ namespace Emby.Server.Implementations.Data
}
else
{
- query.OrderBy = new []
+ query.OrderBy = new[]
{
("SearchScore", SortOrder.Descending),
(ItemSortBy.SortName, SortOrder.Ascending)
};
}
- var orderBy = query.OrderBy;
- if (orderBy.Length == 0)
+ if (orderBy.Count == 0)
{
return string.Empty;
}
@@ -2913,14 +2944,8 @@ namespace Emby.Server.Implementations.Data
return " ORDER BY " + string.Join(",", orderBy.Select(i =>
{
var columnMap = MapOrderByField(i.Item1, query);
- var columnAscending = i.Item2 == SortOrder.Ascending;
- const bool enableOrderInversion = false;
- if (columnMap.Item2 && enableOrderInversion)
- {
- columnAscending = !columnAscending;
- }
- var sortOrder = columnAscending ? "ASC" : "DESC";
+ var sortOrder = i.Item2 == SortOrder.Ascending ? "ASC" : "DESC";
return columnMap.Item1 + " " + sortOrder;
}));
@@ -4599,10 +4624,20 @@ namespace Emby.Server.Implementations.Data
if (query.ExcludeInheritedTags.Length > 0)
{
- var tagValues = query.ExcludeInheritedTags.Select(i => "'" + GetCleanValue(i) + "'");
- var tagValuesList = string.Join(",", tagValues);
-
- whereClauses.Add("((select CleanValue from itemvalues where ItemId=Guid and Type=6 and cleanvalue in (" + tagValuesList + ")) is null)");
+ var paramName = "@ExcludeInheritedTags";
+ if (statement == null)
+ {
+ int index = 0;
+ string excludedTags = string.Join(",", query.ExcludeInheritedTags.Select(t => paramName + index++));
+ whereClauses.Add("((select CleanValue from itemvalues where ItemId=Guid and Type=6 and cleanvalue in (" + excludedTags + ")) is null)");
+ }
+ else
+ {
+ for (int index = 0; index < query.ExcludeInheritedTags.Length; index++)
+ {
+ statement.TryBind(paramName + index, GetCleanValue(query.ExcludeInheritedTags[index]));
+ }
+ }
}
if (query.SeriesStatuses.Length > 0)
@@ -6132,5 +6167,175 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
return item;
}
+
+ public List<MediaAttachment> GetMediaAttachments(MediaAttachmentQuery query)
+ {
+ CheckDisposed();
+
+ if (query == null)
+ {
+ throw new ArgumentNullException(nameof(query));
+ }
+
+ var cmdText = "select "
+ + string.Join(",", _mediaAttachmentSaveColumns)
+ + " from mediaattachments where"
+ + " ItemId=@ItemId";
+
+ if (query.Index.HasValue)
+ {
+ cmdText += " AND AttachmentIndex=@AttachmentIndex";
+ }
+
+ cmdText += " order by AttachmentIndex ASC";
+
+ var list = new List<MediaAttachment>();
+ using (var connection = GetConnection(true))
+ using (var statement = PrepareStatement(connection, cmdText))
+ {
+ statement.TryBind("@ItemId", query.ItemId.ToByteArray());
+
+ if (query.Index.HasValue)
+ {
+ statement.TryBind("@AttachmentIndex", query.Index.Value);
+ }
+
+ foreach (var row in statement.ExecuteQuery())
+ {
+ list.Add(GetMediaAttachment(row));
+ }
+ }
+
+ return list;
+ }
+
+ public void SaveMediaAttachments(
+ Guid id,
+ IReadOnlyList<MediaAttachment> attachments,
+ CancellationToken cancellationToken)
+ {
+ CheckDisposed();
+ if (id == Guid.Empty)
+ {
+ throw new ArgumentException(nameof(id));
+ }
+
+ if (attachments == null)
+ {
+ throw new ArgumentNullException(nameof(attachments));
+ }
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ using (var connection = GetConnection())
+ {
+ connection.RunInTransaction(db =>
+ {
+ var itemIdBlob = id.ToByteArray();
+
+ db.Execute("delete from mediaattachments where ItemId=@ItemId", itemIdBlob);
+
+ InsertMediaAttachments(itemIdBlob, attachments, db, cancellationToken);
+
+ }, TransactionMode);
+ }
+ }
+
+ private void InsertMediaAttachments(
+ byte[] idBlob,
+ IReadOnlyList<MediaAttachment> attachments,
+ IDatabaseConnection db,
+ CancellationToken cancellationToken)
+ {
+ const int InsertAtOnce = 10;
+
+ for (var startIndex = 0; startIndex < attachments.Count; startIndex += InsertAtOnce)
+ {
+ var insertText = new StringBuilder(_mediaAttachmentInsertPrefix);
+
+ var endIndex = Math.Min(attachments.Count, startIndex + InsertAtOnce);
+
+ for (var i = startIndex; i < endIndex; i++)
+ {
+ var index = i.ToString(CultureInfo.InvariantCulture);
+ insertText.Append("(@ItemId, ");
+
+ foreach (var column in _mediaAttachmentSaveColumns.Skip(1))
+ {
+ insertText.Append("@" + column + index + ",");
+ }
+
+ insertText.Length -= 1;
+
+ insertText.Append("),");
+ }
+
+ insertText.Length--;
+
+ cancellationToken.ThrowIfCancellationRequested();
+
+ using (var statement = PrepareStatement(db, insertText.ToString()))
+ {
+ statement.TryBind("@ItemId", idBlob);
+
+ for (var i = startIndex; i < endIndex; i++)
+ {
+ var index = i.ToString(CultureInfo.InvariantCulture);
+
+ var attachment = attachments[i];
+
+ statement.TryBind("@AttachmentIndex" + index, attachment.Index);
+ statement.TryBind("@Codec" + index, attachment.Codec);
+ statement.TryBind("@CodecTag" + index, attachment.CodecTag);
+ statement.TryBind("@Comment" + index, attachment.Comment);
+ statement.TryBind("@FileName" + index, attachment.FileName);
+ statement.TryBind("@MimeType" + index, attachment.MimeType);
+ }
+
+ statement.Reset();
+ statement.MoveNext();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Gets the attachment.
+ /// </summary>
+ /// <param name="reader">The reader.</param>
+ /// <returns>MediaAttachment</returns>
+ private MediaAttachment GetMediaAttachment(IReadOnlyList<IResultSetValue> reader)
+ {
+ var item = new MediaAttachment
+ {
+ Index = reader[1].ToInt()
+ };
+
+ if (reader[2].SQLiteType != SQLiteType.Null)
+ {
+ item.Codec = reader[2].ToString();
+ }
+
+ if (reader[2].SQLiteType != SQLiteType.Null)
+ {
+ item.CodecTag = reader[3].ToString();
+ }
+
+ if (reader[4].SQLiteType != SQLiteType.Null)
+ {
+ item.Comment = reader[4].ToString();
+ }
+
+ if (reader[6].SQLiteType != SQLiteType.Null)
+ {
+ item.FileName = reader[5].ToString();
+ }
+
+ if (reader[6].SQLiteType != SQLiteType.Null)
+ {
+ item.MimeType = reader[6].ToString();
+ }
+
+ return item;
+ }
}
}
diff --git a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs
index 26ac17bdc..22955850a 100644
--- a/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteUserDataRepository.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.IO;
diff --git a/Emby.Server.Implementations/Data/SqliteUserRepository.cs b/Emby.Server.Implementations/Data/SqliteUserRepository.cs
index 26798993b..a042320c9 100644
--- a/Emby.Server.Implementations/Data/SqliteUserRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteUserRepository.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.IO;
diff --git a/Emby.Server.Implementations/Data/TypeMapper.cs b/Emby.Server.Implementations/Data/TypeMapper.cs
index 0e67affbf..7044b1d19 100644
--- a/Emby.Server.Implementations/Data/TypeMapper.cs
+++ b/Emby.Server.Implementations/Data/TypeMapper.cs
@@ -5,25 +5,22 @@ using System.Linq;
namespace Emby.Server.Implementations.Data
{
/// <summary>
- /// Class TypeMapper
+ /// Class TypeMapper.
/// </summary>
public class TypeMapper
{
/// <summary>
- /// This holds all the types in the running assemblies so that we can de-serialize properly when we don't have strong types
+ /// This holds all the types in the running assemblies
+ /// so that we can de-serialize properly when we don't have strong types.
/// </summary>
private readonly ConcurrentDictionary<string, Type> _typeMap = new ConcurrentDictionary<string, Type>();
- public TypeMapper()
- {
- }
-
/// <summary>
/// Gets the type.
/// </summary>
/// <param name="typeName">Name of the type.</param>
/// <returns>Type.</returns>
- /// <exception cref="ArgumentNullException"></exception>
+ /// <exception cref="ArgumentNullException"><c>typeName</c> is null.</exception>
public Type GetType(string typeName)
{
if (string.IsNullOrEmpty(typeName))
diff --git a/Emby.Server.Implementations/Devices/DeviceId.cs b/Emby.Server.Implementations/Devices/DeviceId.cs
index 7344dc72f..f0d43e665 100644
--- a/Emby.Server.Implementations/Devices/DeviceId.cs
+++ b/Emby.Server.Implementations/Devices/DeviceId.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Globalization;
using System.IO;
diff --git a/Emby.Server.Implementations/Devices/DeviceManager.cs b/Emby.Server.Implementations/Devices/DeviceManager.cs
index 36d441851..2393f1f45 100644
--- a/Emby.Server.Implementations/Devices/DeviceManager.cs
+++ b/Emby.Server.Implementations/Devices/DeviceManager.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Globalization;
diff --git a/Emby.Server.Implementations/Diagnostics/CommonProcess.cs b/Emby.Server.Implementations/Diagnostics/CommonProcess.cs
index 175a8f3ce..bfa49ac5f 100644
--- a/Emby.Server.Implementations/Diagnostics/CommonProcess.cs
+++ b/Emby.Server.Implementations/Diagnostics/CommonProcess.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Diagnostics;
using System.IO;
diff --git a/Emby.Server.Implementations/Diagnostics/ProcessFactory.cs b/Emby.Server.Implementations/Diagnostics/ProcessFactory.cs
index 14aadaaae..02ad3c1a8 100644
--- a/Emby.Server.Implementations/Diagnostics/ProcessFactory.cs
+++ b/Emby.Server.Implementations/Diagnostics/ProcessFactory.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using MediaBrowser.Model.Diagnostics;
namespace Emby.Server.Implementations.Diagnostics
diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs
index 6c0e32e05..3d622b3fc 100644
--- a/Emby.Server.Implementations/Dto/DtoService.cs
+++ b/Emby.Server.Implementations/Dto/DtoService.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Globalization;
diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
index eb9069c44..7ae6f38a1 100644
--- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj
+++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
@@ -15,12 +15,12 @@
<ProjectReference Include="..\MediaBrowser.LocalMetadata\MediaBrowser.LocalMetadata.csproj" />
<ProjectReference Include="..\Emby.Photos\Emby.Photos.csproj" />
<ProjectReference Include="..\Emby.Drawing\Emby.Drawing.csproj" />
- <ProjectReference Include="..\Emby.XmlTv\Emby.XmlTv\Emby.XmlTv.csproj" />
<ProjectReference Include="..\MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="IPNetwork2" Version="2.4.0.126" />
+ <PackageReference Include="Jellyfin.XmlTv" Version="10.4.3" />
<PackageReference Include="Microsoft.AspNetCore.Hosting" Version="2.2.7" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.Server.Abstractions" Version="2.2.0" />
@@ -29,7 +29,6 @@
<PackageReference Include="Microsoft.AspNetCore.ResponseCompression" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.WebSockets" Version="2.2.1" />
- <PackageReference Include="Microsoft.Extensions.Logging" Version="3.0.1" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.0.1" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="3.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.0.1" />
@@ -37,6 +36,7 @@
<PackageReference Include="ServiceStack.Text.Core" Version="5.7.0" />
<PackageReference Include="sharpcompress" Version="0.24.0" />
<PackageReference Include="SQLitePCL.pretty.netstandard" Version="2.0.1" />
+ <PackageReference Include="System.Interactive.Async" Version="4.0.0" />
</ItemGroup>
<ItemGroup>
@@ -49,7 +49,7 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
- <!-- Code analysers-->
+ <!-- Code Analyzers-->
<ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.7" />
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" />
diff --git a/Emby.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs b/Emby.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs
index 19ea09359..d69b0909d 100644
--- a/Emby.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs
+++ b/Emby.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Linq;
using System.Threading;
diff --git a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
index a2619367d..e290c62e1 100644
--- a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
+++ b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Net;
diff --git a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs
index 24906220d..5f938e59a 100644
--- a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs
+++ b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Globalization;
diff --git a/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs b/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs
index 0186da9e1..dbb3503c4 100644
--- a/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs
+++ b/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Linq;
using System.Threading;
diff --git a/Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs b/Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs
index 3a7516dca..f00996b5f 100644
--- a/Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs
+++ b/Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
-using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Library;
@@ -12,42 +11,51 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.EntryPoints
{
/// <summary>
- /// Class RefreshUsersMetadata
+ /// Class RefreshUsersMetadata.
/// </summary>
public class RefreshUsersMetadata : IScheduledTask, IConfigurableScheduledTask
{
private readonly ILogger _logger;
+
/// <summary>
- /// The _user manager
+ /// The user manager.
/// </summary>
private readonly IUserManager _userManager;
private IFileSystem _fileSystem;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RefreshUsersMetadata" /> class.
+ /// </summary>
+ public RefreshUsersMetadata(ILogger logger, IUserManager userManager, IFileSystem fileSystem)
+ {
+ _logger = logger;
+ _userManager = userManager;
+ _fileSystem = fileSystem;
+ }
+
+ /// <inheritdoc />
public string Name => "Refresh Users";
+ /// <inheritdoc />
public string Key => "RefreshUsers";
+ /// <inheritdoc />
public string Description => "Refresh user infos";
+ /// <inheritdoc />
public string Category => "Library";
+ /// <inheritdoc />
public bool IsHidden => true;
+ /// <inheritdoc />
public bool IsEnabled => true;
+ /// <inheritdoc />
public bool IsLogged => true;
- /// <summary>
- /// Initializes a new instance of the <see cref="RefreshUsersMetadata" /> class.
- /// </summary>
- public RefreshUsersMetadata(ILogger logger, IUserManager userManager, IFileSystem fileSystem)
- {
- _logger = logger;
- _userManager = userManager;
- _fileSystem = fileSystem;
- }
-
+ /// <inheritdoc />
public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
{
foreach (var user in _userManager.Users)
@@ -58,9 +66,10 @@ namespace Emby.Server.Implementations.EntryPoints
}
}
+ /// <inheritdoc />
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
{
- return new List<TaskTriggerInfo>
+ return new[]
{
new TaskTriggerInfo
{
diff --git a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs
index 3ff8d9968..e1dbb663b 100644
--- a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs
+++ b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs
@@ -16,33 +16,46 @@ using MediaBrowser.Model.Tasks;
namespace Emby.Server.Implementations.EntryPoints
{
/// <summary>
- /// Class WebSocketEvents
+ /// Class WebSocketEvents.
/// </summary>
public class ServerEventNotifier : IServerEntryPoint
{
/// <summary>
- /// The _user manager
+ /// The user manager.
/// </summary>
private readonly IUserManager _userManager;
/// <summary>
- /// The _installation manager
+ /// The installation manager.
/// </summary>
private readonly IInstallationManager _installationManager;
/// <summary>
- /// The _kernel
+ /// The kernel.
/// </summary>
private readonly IServerApplicationHost _appHost;
/// <summary>
- /// The _task manager
+ /// The task manager.
/// </summary>
private readonly ITaskManager _taskManager;
private readonly ISessionManager _sessionManager;
- public ServerEventNotifier(IServerApplicationHost appHost, IUserManager userManager, IInstallationManager installationManager, ITaskManager taskManager, ISessionManager sessionManager)
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ServerEventNotifier"/> class.
+ /// </summary>
+ /// <param name="appHost">The application host.</param>
+ /// <param name="userManager">The user manager.</param>
+ /// <param name="installationManager">The installation manager.</param>
+ /// <param name="taskManager">The task manager.</param>
+ /// <param name="sessionManager">The session manager.</param>
+ public ServerEventNotifier(
+ IServerApplicationHost appHost,
+ IUserManager userManager,
+ IInstallationManager installationManager,
+ ITaskManager taskManager,
+ ISessionManager sessionManager)
{
_userManager = userManager;
_installationManager = installationManager;
@@ -51,47 +64,48 @@ namespace Emby.Server.Implementations.EntryPoints
_sessionManager = sessionManager;
}
+ /// <inheritdoc />
public Task RunAsync()
{
- _userManager.UserDeleted += userManager_UserDeleted;
- _userManager.UserUpdated += userManager_UserUpdated;
- _userManager.UserPolicyUpdated += _userManager_UserPolicyUpdated;
- _userManager.UserConfigurationUpdated += _userManager_UserConfigurationUpdated;
+ _userManager.UserDeleted += OnUserDeleted;
+ _userManager.UserUpdated += OnUserUpdated;
+ _userManager.UserPolicyUpdated += OnUserPolicyUpdated;
+ _userManager.UserConfigurationUpdated += OnUserConfigurationUpdated;
- _appHost.HasPendingRestartChanged += kernel_HasPendingRestartChanged;
+ _appHost.HasPendingRestartChanged += OnHasPendingRestartChanged;
- _installationManager.PluginUninstalled += InstallationManager_PluginUninstalled;
- _installationManager.PackageInstalling += _installationManager_PackageInstalling;
- _installationManager.PackageInstallationCancelled += _installationManager_PackageInstallationCancelled;
- _installationManager.PackageInstallationCompleted += _installationManager_PackageInstallationCompleted;
- _installationManager.PackageInstallationFailed += _installationManager_PackageInstallationFailed;
+ _installationManager.PluginUninstalled += OnPluginUninstalled;
+ _installationManager.PackageInstalling += OnPackageInstalling;
+ _installationManager.PackageInstallationCancelled += OnPackageInstallationCancelled;
+ _installationManager.PackageInstallationCompleted += OnPackageInstallationCompleted;
+ _installationManager.PackageInstallationFailed += OnPackageInstallationFailed;
- _taskManager.TaskCompleted += _taskManager_TaskCompleted;
+ _taskManager.TaskCompleted += OnTaskCompleted;
return Task.CompletedTask;
}
- void _installationManager_PackageInstalling(object sender, InstallationEventArgs e)
+ private void OnPackageInstalling(object sender, InstallationEventArgs e)
{
SendMessageToAdminSessions("PackageInstalling", e.InstallationInfo);
}
- void _installationManager_PackageInstallationCancelled(object sender, InstallationEventArgs e)
+ private void OnPackageInstallationCancelled(object sender, InstallationEventArgs e)
{
SendMessageToAdminSessions("PackageInstallationCancelled", e.InstallationInfo);
}
- void _installationManager_PackageInstallationCompleted(object sender, InstallationEventArgs e)
+ private void OnPackageInstallationCompleted(object sender, InstallationEventArgs e)
{
SendMessageToAdminSessions("PackageInstallationCompleted", e.InstallationInfo);
}
- void _installationManager_PackageInstallationFailed(object sender, InstallationFailedEventArgs e)
+ private void OnPackageInstallationFailed(object sender, InstallationFailedEventArgs e)
{
SendMessageToAdminSessions("PackageInstallationFailed", e.InstallationInfo);
}
- void _taskManager_TaskCompleted(object sender, TaskCompletionEventArgs e)
+ private void OnTaskCompleted(object sender, TaskCompletionEventArgs e)
{
SendMessageToAdminSessions("ScheduledTaskEnded", e.Result);
}
@@ -101,7 +115,7 @@ namespace Emby.Server.Implementations.EntryPoints
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The e.</param>
- void InstallationManager_PluginUninstalled(object sender, GenericEventArgs<IPlugin> e)
+ private void OnPluginUninstalled(object sender, GenericEventArgs<IPlugin> e)
{
SendMessageToAdminSessions("PluginUninstalled", e.Argument.GetPluginInfo());
}
@@ -111,7 +125,7 @@ namespace Emby.Server.Implementations.EntryPoints
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
- void kernel_HasPendingRestartChanged(object sender, EventArgs e)
+ private void OnHasPendingRestartChanged(object sender, EventArgs e)
{
_sessionManager.SendRestartRequiredNotification(CancellationToken.None);
}
@@ -121,7 +135,7 @@ namespace Emby.Server.Implementations.EntryPoints
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The e.</param>
- void userManager_UserUpdated(object sender, GenericEventArgs<User> e)
+ private void OnUserUpdated(object sender, GenericEventArgs<User> e)
{
var dto = _userManager.GetUserDto(e.Argument);
@@ -133,19 +147,19 @@ namespace Emby.Server.Implementations.EntryPoints
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="e">The e.</param>
- void userManager_UserDeleted(object sender, GenericEventArgs<User> e)
+ private void OnUserDeleted(object sender, GenericEventArgs<User> e)
{
SendMessageToUserSession(e.Argument, "UserDeleted", e.Argument.Id.ToString("N", CultureInfo.InvariantCulture));
}
- void _userManager_UserPolicyUpdated(object sender, GenericEventArgs<User> e)
+ private void OnUserPolicyUpdated(object sender, GenericEventArgs<User> e)
{
var dto = _userManager.GetUserDto(e.Argument);
SendMessageToUserSession(e.Argument, "UserPolicyUpdated", dto);
}
- void _userManager_UserConfigurationUpdated(object sender, GenericEventArgs<User> e)
+ private void OnUserConfigurationUpdated(object sender, GenericEventArgs<User> e)
{
var dto = _userManager.GetUserDto(e.Argument);
@@ -168,7 +182,11 @@ namespace Emby.Server.Implementations.EntryPoints
{
try
{
- await _sessionManager.SendMessageToUserSessions(new List<Guid> { user.Id }, name, data, CancellationToken.None);
+ await _sessionManager.SendMessageToUserSessions(
+ new List<Guid> { user.Id },
+ name,
+ data,
+ CancellationToken.None).ConfigureAwait(false);
}
catch (Exception)
{
@@ -176,12 +194,11 @@ namespace Emby.Server.Implementations.EntryPoints
}
}
- /// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- /// </summary>
+ /// <inheritdoc />
public void Dispose()
{
Dispose(true);
+ GC.SuppressFinalize(this);
}
/// <summary>
@@ -192,18 +209,20 @@ namespace Emby.Server.Implementations.EntryPoints
{
if (dispose)
{
- _userManager.UserDeleted -= userManager_UserDeleted;
- _userManager.UserUpdated -= userManager_UserUpdated;
- _userManager.UserPolicyUpdated -= _userManager_UserPolicyUpdated;
- _userManager.UserConfigurationUpdated -= _userManager_UserConfigurationUpdated;
-
- _installationManager.PluginUninstalled -= InstallationManager_PluginUninstalled;
- _installationManager.PackageInstalling -= _installationManager_PackageInstalling;
- _installationManager.PackageInstallationCancelled -= _installationManager_PackageInstallationCancelled;
- _installationManager.PackageInstallationCompleted -= _installationManager_PackageInstallationCompleted;
- _installationManager.PackageInstallationFailed -= _installationManager_PackageInstallationFailed;
-
- _appHost.HasPendingRestartChanged -= kernel_HasPendingRestartChanged;
+ _userManager.UserDeleted -= OnUserDeleted;
+ _userManager.UserUpdated -= OnUserUpdated;
+ _userManager.UserPolicyUpdated -= OnUserPolicyUpdated;
+ _userManager.UserConfigurationUpdated -= OnUserConfigurationUpdated;
+
+ _installationManager.PluginUninstalled -= OnPluginUninstalled;
+ _installationManager.PackageInstalling -= OnPackageInstalling;
+ _installationManager.PackageInstallationCancelled -= OnPackageInstallationCancelled;
+ _installationManager.PackageInstallationCompleted -= OnPackageInstallationCompleted;
+ _installationManager.PackageInstallationFailed -= OnPackageInstallationFailed;
+
+ _appHost.HasPendingRestartChanged -= OnHasPendingRestartChanged;
+
+ _taskManager.TaskCompleted -= OnTaskCompleted;
}
}
}
diff --git a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs
index 8be6db87d..161788c63 100644
--- a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs
+++ b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs
@@ -8,21 +8,28 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.EntryPoints
{
/// <summary>
- /// Class StartupWizard
+ /// Class StartupWizard.
/// </summary>
public class StartupWizard : IServerEntryPoint
{
/// <summary>
- /// The _app host
+ /// The app host.
/// </summary>
private readonly IServerApplicationHost _appHost;
+
/// <summary>
- /// The _user manager
+ /// The user manager.
/// </summary>
private readonly ILogger _logger;
private IServerConfigurationManager _config;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="StartupWizard"/> class.
+ /// </summary>
+ /// <param name="appHost">The application host.</param>
+ /// <param name="logger">The logger.</param>
+ /// <param name="config">The configuration manager.</param>
public StartupWizard(IServerApplicationHost appHost, ILogger logger, IServerConfigurationManager config)
{
_appHost = appHost;
@@ -30,9 +37,7 @@ namespace Emby.Server.Implementations.EntryPoints
_config = config;
}
- /// <summary>
- /// Runs this instance.
- /// </summary>
+ /// <inheritdoc />
public Task RunAsync()
{
if (!_appHost.CanLaunchWebBrowser)
@@ -57,9 +62,7 @@ namespace Emby.Server.Implementations.EntryPoints
return Task.CompletedTask;
}
- /// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- /// </summary>
+ /// <inheritdoc />
public void Dispose()
{
}
diff --git a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs
index 5b90dc1fb..9ee219854 100644
--- a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs
+++ b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs
@@ -10,30 +10,36 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.EntryPoints
{
/// <summary>
- /// Class UdpServerEntryPoint
+ /// Class UdpServerEntryPoint.
/// </summary>
public class UdpServerEntryPoint : IServerEntryPoint
{
/// <summary>
- /// Gets or sets the UDP server.
+ /// The port of the UDP server.
/// </summary>
- /// <value>The UDP server.</value>
- private UdpServer UdpServer { get; set; }
+ public const int PortNumber = 7359;
/// <summary>
- /// The _logger
+ /// The logger.
/// </summary>
private readonly ILogger _logger;
private readonly ISocketFactory _socketFactory;
private readonly IServerApplicationHost _appHost;
private readonly IJsonSerializer _json;
- public const int PortNumber = 7359;
+ /// <summary>
+ /// The UDP server.
+ /// </summary>
+ private UdpServer _udpServer;
/// <summary>
/// Initializes a new instance of the <see cref="UdpServerEntryPoint" /> class.
/// </summary>
- public UdpServerEntryPoint(ILogger logger, IServerApplicationHost appHost, IJsonSerializer json, ISocketFactory socketFactory)
+ public UdpServerEntryPoint(
+ ILogger logger,
+ IServerApplicationHost appHost,
+ IJsonSerializer json,
+ ISocketFactory socketFactory)
{
_logger = logger;
_appHost = appHost;
@@ -41,9 +47,7 @@ namespace Emby.Server.Implementations.EntryPoints
_socketFactory = socketFactory;
}
- /// <summary>
- /// Runs this instance.
- /// </summary>
+ /// <inheritdoc />
public Task RunAsync()
{
var udpServer = new UdpServer(_logger, _appHost, _json, _socketFactory);
@@ -52,7 +56,7 @@ namespace Emby.Server.Implementations.EntryPoints
{
udpServer.Start(PortNumber);
- UdpServer = udpServer;
+ _udpServer = udpServer;
}
catch (Exception ex)
{
@@ -62,12 +66,11 @@ namespace Emby.Server.Implementations.EntryPoints
return Task.CompletedTask;
}
- /// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- /// </summary>
+ /// <inheritdoc />
public void Dispose()
{
Dispose(true);
+ GC.SuppressFinalize(this);
}
/// <summary>
@@ -78,9 +81,9 @@ namespace Emby.Server.Implementations.EntryPoints
{
if (dispose)
{
- if (UdpServer != null)
+ if (_udpServer != null)
{
- UdpServer.Dispose();
+ _udpServer.Dispose();
}
}
}
diff --git a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs
index bae3422ff..e431da148 100644
--- a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs
+++ b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Globalization;
diff --git a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs
index 2da0191dd..50233ea48 100644
--- a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs
+++ b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs
@@ -282,6 +282,7 @@ namespace Emby.Server.Implementations.HttpClientManager
};
}
+ /// <inheritdoc />
public Task<HttpResponseInfo> Post(HttpRequestOptions options)
=> SendAsync(options, HttpMethod.Post);
diff --git a/Emby.Server.Implementations/HttpServer/FileWriter.cs b/Emby.Server.Implementations/HttpServer/FileWriter.cs
index 2c7e81361..c1c8c3eb3 100644
--- a/Emby.Server.Implementations/HttpServer/FileWriter.cs
+++ b/Emby.Server.Implementations/HttpServer/FileWriter.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Globalization;
diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
index 6dd016f8a..2aefc9fe5 100644
--- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
+++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Diagnostics;
diff --git a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
index b5cfb6b09..a62b4e7af 100644
--- a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
+++ b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -5,12 +7,10 @@ using System.IO;
using System.IO.Compression;
using System.Net;
using System.Runtime.Serialization;
-using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using Emby.Server.Implementations.Services;
-using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Serialization;
@@ -24,12 +24,12 @@ using MimeTypes = MediaBrowser.Model.Net.MimeTypes;
namespace Emby.Server.Implementations.HttpServer
{
/// <summary>
- /// Class HttpResultFactory
+ /// Class HttpResultFactory.
/// </summary>
public class HttpResultFactory : IHttpResultFactory
{
/// <summary>
- /// The _logger
+ /// The logger.
/// </summary>
private readonly ILogger _logger;
private readonly IFileSystem _fileSystem;
diff --git a/Emby.Server.Implementations/HttpServer/IHttpListener.cs b/Emby.Server.Implementations/HttpServer/IHttpListener.cs
index 005656d2c..501593725 100644
--- a/Emby.Server.Implementations/HttpServer/IHttpListener.cs
+++ b/Emby.Server.Implementations/HttpServer/IHttpListener.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Threading;
using System.Threading.Tasks;
diff --git a/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs b/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs
index 320136d11..8b9028f6b 100644
--- a/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs
+++ b/Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Globalization;
diff --git a/Emby.Server.Implementations/HttpServer/ResponseFilter.cs b/Emby.Server.Implementations/HttpServer/ResponseFilter.cs
index 3e731366e..5e0466629 100644
--- a/Emby.Server.Implementations/HttpServer/ResponseFilter.cs
+++ b/Emby.Server.Implementations/HttpServer/ResponseFilter.cs
@@ -8,11 +8,17 @@ using Microsoft.Net.Http.Headers;
namespace Emby.Server.Implementations.HttpServer
{
+ /// <summary>
+ /// Class ResponseFilter.
+ /// </summary>
public class ResponseFilter
{
- private static readonly CultureInfo _usCulture = CultureInfo.ReadOnly(new CultureInfo("en-US"));
private readonly ILogger _logger;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="ResponseFilter"/> class.
+ /// </summary>
+ /// <param name="logger">The logger.</param>
public ResponseFilter(ILogger logger)
{
_logger = logger;
@@ -37,7 +43,7 @@ namespace Emby.Server.Implementations.HttpServer
if (!string.IsNullOrEmpty(exception.Message))
{
- var error = exception.Message.Replace(Environment.NewLine, " ");
+ var error = exception.Message.Replace(Environment.NewLine, " ", StringComparison.Ordinal);
error = RemoveControlCharacters(error);
res.Headers.Add("X-Application-Error-Code", error);
@@ -55,7 +61,7 @@ namespace Emby.Server.Implementations.HttpServer
if (hasHeaders.Headers.TryGetValue(HeaderNames.ContentLength, out string contentLength)
&& !string.IsNullOrEmpty(contentLength))
{
- var length = long.Parse(contentLength, _usCulture);
+ var length = long.Parse(contentLength, CultureInfo.InvariantCulture);
if (length > 0)
{
diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs
index 594f46498..58421aaf1 100644
--- a/Emby.Server.Implementations/HttpServer/Security/AuthService.cs
+++ b/Emby.Server.Implementations/HttpServer/Security/AuthService.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Linq;
using Emby.Server.Implementations.SocketSharp;
diff --git a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
index 457448604..129faeaab 100644
--- a/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
+++ b/Emby.Server.Implementations/HttpServer/Security/AuthorizationContext.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Linq;
diff --git a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs b/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs
index 81e11d312..166952c64 100644
--- a/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs
+++ b/Emby.Server.Implementations/HttpServer/Security/SessionContext.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
diff --git a/Emby.Server.Implementations/HttpServer/StreamWriter.cs b/Emby.Server.Implementations/HttpServer/StreamWriter.cs
index 194d04441..5afc51dbc 100644
--- a/Emby.Server.Implementations/HttpServer/StreamWriter.cs
+++ b/Emby.Server.Implementations/HttpServer/StreamWriter.cs
@@ -10,37 +10,20 @@ using Microsoft.Net.Http.Headers;
namespace Emby.Server.Implementations.HttpServer
{
/// <summary>
- /// Class StreamWriter
+ /// Class StreamWriter.
/// </summary>
public class StreamWriter : IAsyncStreamWriter, IHasHeaders
{
/// <summary>
- /// Gets or sets the source stream.
- /// </summary>
- /// <value>The source stream.</value>
- private Stream SourceStream { get; set; }
-
- private byte[] SourceBytes { get; set; }
-
- /// <summary>
- /// The _options
+ /// The options.
/// </summary>
private readonly IDictionary<string, string> _options = new Dictionary<string, string>();
- /// <summary>
- /// Gets the options.
- /// </summary>
- /// <value>The options.</value>
- public IDictionary<string, string> Headers => _options;
-
- public Action OnComplete { get; set; }
- public Action OnError { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="StreamWriter" /> class.
/// </summary>
/// <param name="source">The source.</param>
/// <param name="contentType">Type of the content.</param>
- /// <param name="logger">The logger.</param>
public StreamWriter(Stream source, string contentType)
{
if (string.IsNullOrEmpty(contentType))
@@ -65,6 +48,7 @@ namespace Emby.Server.Implementations.HttpServer
/// </summary>
/// <param name="source">The source.</param>
/// <param name="contentType">Type of the content.</param>
+ /// <param name="contentLength">The content length.</param>
public StreamWriter(byte[] source, string contentType, int contentLength)
{
if (string.IsNullOrEmpty(contentType))
@@ -78,6 +62,31 @@ namespace Emby.Server.Implementations.HttpServer
Headers[HeaderNames.ContentType] = contentType;
}
+ /// <summary>
+ /// Gets or sets the source stream.
+ /// </summary>
+ /// <value>The source stream.</value>
+ private Stream SourceStream { get; set; }
+
+ private byte[] SourceBytes { get; set; }
+
+ /// <summary>
+ /// Gets the options.
+ /// </summary>
+ /// <value>The options.</value>
+ public IDictionary<string, string> Headers => _options;
+
+ /// <summary>
+ /// Fires when complete.
+ /// </summary>
+ public Action OnComplete { get; set; }
+
+ /// <summary>
+ /// Fires when an error occours.
+ /// </summary>
+ public Action OnError { get; set; }
+
+ /// <inheritdoc />
public async Task WriteToAsync(Stream responseStream, CancellationToken cancellationToken)
{
try
@@ -98,19 +107,13 @@ namespace Emby.Server.Implementations.HttpServer
}
catch
{
- if (OnError != null)
- {
- OnError();
- }
+ OnError?.Invoke();
throw;
}
finally
{
- if (OnComplete != null)
- {
- OnComplete();
- }
+ OnComplete?.Invoke();
}
}
}
diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs
index 54a16040f..2292d86a4 100644
--- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs
+++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs
@@ -7,7 +7,6 @@ using Emby.Server.Implementations.Net;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Serialization;
-using MediaBrowser.Model.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using UtfUnknown;
@@ -15,60 +14,24 @@ using UtfUnknown;
namespace Emby.Server.Implementations.HttpServer
{
/// <summary>
- /// Class WebSocketConnection
+ /// Class WebSocketConnection.
/// </summary>
public class WebSocketConnection : IWebSocketConnection
{
- public event EventHandler<EventArgs> Closed;
-
- /// <summary>
- /// The _socket
- /// </summary>
- private readonly IWebSocket _socket;
-
/// <summary>
- /// The _remote end point
- /// </summary>
- public string RemoteEndPoint { get; private set; }
-
- /// <summary>
- /// The logger
+ /// The logger.
/// </summary>
private readonly ILogger _logger;
/// <summary>
- /// The _json serializer
+ /// The json serializer.
/// </summary>
private readonly IJsonSerializer _jsonSerializer;
/// <summary>
- /// Gets or sets the receive action.
- /// </summary>
- /// <value>The receive action.</value>
- public Func<WebSocketMessageInfo, Task> OnReceive { get; set; }
-
- /// <summary>
- /// Gets the last activity date.
- /// </summary>
- /// <value>The last activity date.</value>
- public DateTime LastActivityDate { get; private set; }
-
- /// <summary>
- /// Gets the id.
+ /// The socket.
/// </summary>
- /// <value>The id.</value>
- public Guid Id { get; private set; }
-
- /// <summary>
- /// Gets or sets the URL.
- /// </summary>
- /// <value>The URL.</value>
- public string Url { get; set; }
- /// <summary>
- /// Gets or sets the query string.
- /// </summary>
- /// <value>The query string.</value>
- public IQueryCollection QueryString { get; set; }
+ private readonly IWebSocket _socket;
/// <summary>
/// Initializes a new instance of the <see cref="WebSocketConnection" /> class.
@@ -84,14 +47,17 @@ namespace Emby.Server.Implementations.HttpServer
{
throw new ArgumentNullException(nameof(socket));
}
+
if (string.IsNullOrEmpty(remoteEndPoint))
{
throw new ArgumentNullException(nameof(remoteEndPoint));
}
+
if (jsonSerializer == null)
{
throw new ArgumentNullException(nameof(jsonSerializer));
}
+
if (logger == null)
{
throw new ArgumentNullException(nameof(logger));
@@ -105,10 +71,54 @@ namespace Emby.Server.Implementations.HttpServer
RemoteEndPoint = remoteEndPoint;
_logger = logger;
- socket.Closed += socket_Closed;
+ socket.Closed += OnSocketClosed;
}
- void socket_Closed(object sender, EventArgs e)
+ /// <inheritdoc />
+ public event EventHandler<EventArgs> Closed;
+
+ /// <summary>
+ /// Gets or sets the remote end point.
+ /// </summary>
+ public string RemoteEndPoint { get; private set; }
+
+ /// <summary>
+ /// Gets or sets the receive action.
+ /// </summary>
+ /// <value>The receive action.</value>
+ public Func<WebSocketMessageInfo, Task> OnReceive { get; set; }
+
+ /// <summary>
+ /// Gets the last activity date.
+ /// </summary>
+ /// <value>The last activity date.</value>
+ public DateTime LastActivityDate { get; private set; }
+
+ /// <summary>
+ /// Gets the id.
+ /// </summary>
+ /// <value>The id.</value>
+ public Guid Id { get; private set; }
+
+ /// <summary>
+ /// Gets or sets the URL.
+ /// </summary>
+ /// <value>The URL.</value>
+ public string Url { get; set; }
+
+ /// <summary>
+ /// Gets or sets the query string.
+ /// </summary>
+ /// <value>The query string.</value>
+ public IQueryCollection QueryString { get; set; }
+
+ /// <summary>
+ /// Gets the state.
+ /// </summary>
+ /// <value>The state.</value>
+ public WebSocketState State => _socket.State;
+
+ void OnSocketClosed(object sender, EventArgs e)
{
Closed?.Invoke(this, EventArgs.Empty);
}
@@ -210,6 +220,7 @@ namespace Emby.Server.Implementations.HttpServer
return _socket.SendAsync(buffer, true, cancellationToken);
}
+ /// <inheritdoc />
public Task SendAsync(string text, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(text))
@@ -222,18 +233,11 @@ namespace Emby.Server.Implementations.HttpServer
return _socket.SendAsync(text, true, cancellationToken);
}
- /// <summary>
- /// Gets the state.
- /// </summary>
- /// <value>The state.</value>
- public WebSocketState State => _socket.State;
-
- /// <summary>
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
- /// </summary>
+ /// <inheritdoc />
public void Dispose()
{
Dispose(true);
+ GC.SuppressFinalize(this);
}
/// <summary>
diff --git a/Emby.Server.Implementations/IO/ExtendedFileSystemInfo.cs b/Emby.Server.Implementations/IO/ExtendedFileSystemInfo.cs
index 48b34a3a0..3150f3367 100644
--- a/Emby.Server.Implementations/IO/ExtendedFileSystemInfo.cs
+++ b/Emby.Server.Implementations/IO/ExtendedFileSystemInfo.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
namespace Emby.Server.Implementations.IO
{
public class ExtendedFileSystemInfo
diff --git a/Emby.Server.Implementations/IO/FileRefresher.cs b/Emby.Server.Implementations/IO/FileRefresher.cs
index 40e8ed5dc..4b5b11f01 100644
--- a/Emby.Server.Implementations/IO/FileRefresher.cs
+++ b/Emby.Server.Implementations/IO/FileRefresher.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.IO;
diff --git a/Emby.Server.Implementations/IO/LibraryMonitor.cs b/Emby.Server.Implementations/IO/LibraryMonitor.cs
index aeb541c54..b1fb8cc63 100644
--- a/Emby.Server.Implementations/IO/LibraryMonitor.cs
+++ b/Emby.Server.Implementations/IO/LibraryMonitor.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -16,22 +18,22 @@ namespace Emby.Server.Implementations.IO
public class LibraryMonitor : ILibraryMonitor
{
/// <summary>
- /// The file system watchers
+ /// The file system watchers.
/// </summary>
private readonly ConcurrentDictionary<string, FileSystemWatcher> _fileSystemWatchers = new ConcurrentDictionary<string, FileSystemWatcher>(StringComparer.OrdinalIgnoreCase);
/// <summary>
- /// The affected paths
+ /// The affected paths.
/// </summary>
private readonly List<FileRefresher> _activeRefreshers = new List<FileRefresher>();
/// <summary>
- /// A dynamic list of paths that should be ignored. Added to during our own file sytem modifications.
+ /// A dynamic list of paths that should be ignored. Added to during our own file system modifications.
/// </summary>
private readonly ConcurrentDictionary<string, string> _tempIgnoredPaths = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
/// <summary>
- /// Any file name ending in any of these will be ignored by the watchers
+ /// Any file name ending in any of these will be ignored by the watchers.
/// </summary>
private static readonly HashSet<string> _alwaysIgnoreFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs
index ae8371a32..9568f62df 100644
--- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs
+++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -107,7 +109,7 @@ namespace Emby.Server.Implementations.IO
}
try
{
- return Path.Combine(Path.GetFullPath(folderPath), filePath);
+ return Path.GetFullPath(Path.Combine(folderPath, filePath));
}
catch (ArgumentException)
{
diff --git a/Emby.Server.Implementations/IO/MbLinkShortcutHandler.cs b/Emby.Server.Implementations/IO/MbLinkShortcutHandler.cs
index 5e5e91bb3..e6696b8c4 100644
--- a/Emby.Server.Implementations/IO/MbLinkShortcutHandler.cs
+++ b/Emby.Server.Implementations/IO/MbLinkShortcutHandler.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.IO;
using MediaBrowser.Model.IO;
diff --git a/Emby.Server.Implementations/IO/StreamHelper.cs b/Emby.Server.Implementations/IO/StreamHelper.cs
index 7c8c079e3..40b397edc 100644
--- a/Emby.Server.Implementations/IO/StreamHelper.cs
+++ b/Emby.Server.Implementations/IO/StreamHelper.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Buffers;
using System.IO;
diff --git a/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs b/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs
index 6afcf567a..fd50f156a 100644
--- a/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs
+++ b/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Globalization;
diff --git a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
index 8bdb38784..bc1398332 100644
--- a/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
+++ b/Emby.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
@@ -42,6 +42,10 @@ namespace Emby.Server.Implementations.Library
".grab",
};
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CoreResolutionIgnoreRule"/> class.
+ /// </summary>
+ /// <param name="libraryManager">The library manager.</param>
public CoreResolutionIgnoreRule(ILibraryManager libraryManager)
{
_libraryManager = libraryManager;
diff --git a/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs b/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs
index c043568d5..94f60ea62 100644
--- a/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs
+++ b/Emby.Server.Implementations/Library/DefaultAuthenticationProvider.cs
@@ -10,10 +10,17 @@ using MediaBrowser.Model.Cryptography;
namespace Emby.Server.Implementations.Library
{
+ /// <summary>
+ /// The default authentication provider.
+ /// </summary>
public class DefaultAuthenticationProvider : IAuthenticationProvider, IRequiresResolvedUser
{
private readonly ICryptoProvider _cryptographyProvider;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DefaultAuthenticationProvider"/> class.
+ /// </summary>
+ /// <param name="cryptographyProvider">The cryptography provider.</param>
public DefaultAuthenticationProvider(ICryptoProvider cryptographyProvider)
{
_cryptographyProvider = cryptographyProvider;
@@ -38,12 +45,13 @@ namespace Emby.Server.Implementations.Library
// This is the version that we need to use for local users. Because reasons.
public Task<ProviderAuthenticationResult> Authenticate(string username, string password, User resolvedUser)
{
- bool success = false;
if (resolvedUser == null)
{
throw new ArgumentNullException(nameof(resolvedUser));
}
+ bool success = false;
+
// As long as jellyfin supports passwordless users, we need this little block here to accommodate
if (!HasPassword(resolvedUser) && string.IsNullOrEmpty(password))
{
diff --git a/Emby.Server.Implementations/Library/DefaultPasswordResetProvider.cs b/Emby.Server.Implementations/Library/DefaultPasswordResetProvider.cs
index fa6bbcf91..6c6fbd86f 100644
--- a/Emby.Server.Implementations/Library/DefaultPasswordResetProvider.cs
+++ b/Emby.Server.Implementations/Library/DefaultPasswordResetProvider.cs
@@ -12,6 +12,9 @@ using MediaBrowser.Model.Users;
namespace Emby.Server.Implementations.Library
{
+ /// <summary>
+ /// The default password reset provider.
+ /// </summary>
public class DefaultPasswordResetProvider : IPasswordResetProvider
{
private const string BaseResetFileName = "passwordreset";
@@ -22,6 +25,12 @@ namespace Emby.Server.Implementations.Library
private readonly string _passwordResetFileBase;
private readonly string _passwordResetFileBaseDir;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DefaultPasswordResetProvider"/> class.
+ /// </summary>
+ /// <param name="configurationManager">The configuration manager.</param>
+ /// <param name="jsonSerializer">The JSON serializer.</param>
+ /// <param name="userManager">The user manager.</param>
public DefaultPasswordResetProvider(
IServerConfigurationManager configurationManager,
IJsonSerializer jsonSerializer,
@@ -56,8 +65,8 @@ namespace Emby.Server.Implementations.Library
File.Delete(resetfile);
}
else if (string.Equals(
- spr.Pin.Replace("-", string.Empty),
- pin.Replace("-", string.Empty),
+ spr.Pin.Replace("-", string.Empty, StringComparison.Ordinal),
+ pin.Replace("-", string.Empty, StringComparison.Ordinal),
StringComparison.InvariantCultureIgnoreCase))
{
var resetUser = _userManager.GetUserByName(spr.UserName);
diff --git a/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs b/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs
index a3c879f12..9a7186898 100644
--- a/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs
+++ b/Emby.Server.Implementations/Library/ExclusiveLiveStream.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Globalization;
using System.Threading;
diff --git a/Emby.Server.Implementations/Library/InvalidAuthProvider.cs b/Emby.Server.Implementations/Library/InvalidAuthProvider.cs
index 7913df5e4..dc61aacd7 100644
--- a/Emby.Server.Implementations/Library/InvalidAuthProvider.cs
+++ b/Emby.Server.Implementations/Library/InvalidAuthProvider.cs
@@ -4,37 +4,48 @@ using MediaBrowser.Controller.Entities;
namespace Emby.Server.Implementations.Library
{
+ /// <summary>
+ /// An invalid authentication provider.
+ /// </summary>
public class InvalidAuthProvider : IAuthenticationProvider
{
+ /// <inheritdoc />
public string Name => "InvalidOrMissingAuthenticationProvider";
+ /// <inheritdoc />
public bool IsEnabled => true;
+ /// <inheritdoc />
public Task<ProviderAuthenticationResult> Authenticate(string username, string password)
{
throw new AuthenticationException("User Account cannot login with this provider. The Normal provider for this user cannot be found");
}
+ /// <inheritdoc />
public bool HasPassword(User user)
{
return true;
}
+ /// <inheritdoc />
public Task ChangePassword(User user, string newPassword)
{
return Task.CompletedTask;
}
+ /// <inheritdoc />
public void ChangeEasyPassword(User user, string newPassword, string newPasswordHash)
{
// Nothing here
}
+ /// <inheritdoc />
public string GetPasswordHash(User user)
{
return string.Empty;
}
+ /// <inheritdoc />
public string GetEasyPasswordHash(User user)
{
return string.Empty;
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index 528636ecd..cee51479e 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -390,9 +392,9 @@ namespace Emby.Server.Implementations.Library
// Add this flag to GetDeletePaths if required in the future
var isRequiredForDelete = true;
- foreach (var fileSystemInfo in item.GetDeletePaths().ToList())
+ foreach (var fileSystemInfo in item.GetDeletePaths())
{
- if (File.Exists(fileSystemInfo.FullName))
+ if (Directory.Exists(fileSystemInfo.FullName) || File.Exists(fileSystemInfo.FullName))
{
try
{
@@ -829,7 +831,7 @@ namespace Emby.Server.Implementations.Library
{
Path = path,
IsFolder = isFolder,
- OrderBy = new[] { ItemSortBy.DateCreated }.Select(i => new ValueTuple<string, SortOrder>(i, SortOrder.Descending)).ToArray(),
+ OrderBy = new[] { (ItemSortBy.DateCreated, SortOrder.Descending) },
Limit = 1,
DtoOptions = new DtoOptions(true)
};
@@ -1257,7 +1259,7 @@ namespace Emby.Server.Implementations.Library
public List<BaseItem> GetItemList(InternalItemsQuery query, bool allowExternalContent)
{
- if (query.Recursive && !query.ParentId.Equals(Guid.Empty))
+ if (query.Recursive && query.ParentId != Guid.Empty)
{
var parent = GetItemById(query.ParentId);
if (parent != null)
diff --git a/Emby.Server.Implementations/Library/LiveStreamHelper.cs b/Emby.Server.Implementations/Library/LiveStreamHelper.cs
index 33e6f2434..ed7d8aa40 100644
--- a/Emby.Server.Implementations/Library/LiveStreamHelper.cs
+++ b/Emby.Server.Implementations/Library/LiveStreamHelper.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Globalization;
diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs
index 059b27e87..70d5bd9f4 100644
--- a/Emby.Server.Implementations/Library/MediaSourceManager.cs
+++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -128,6 +130,21 @@ namespace Emby.Server.Implementations.Library
return streams;
}
+ /// <inheritdoc />
+ public List<MediaAttachment> GetMediaAttachments(MediaAttachmentQuery query)
+ {
+ return _itemRepo.GetMediaAttachments(query);
+ }
+
+ /// <inheritdoc />
+ public List<MediaAttachment> GetMediaAttachments(Guid itemId)
+ {
+ return GetMediaAttachments(new MediaAttachmentQuery
+ {
+ ItemId = itemId
+ });
+ }
+
public async Task<List<MediaSourceInfo>> GetPlaybackMediaSources(BaseItem item, User user, bool allowMediaProbe, bool enablePathSubstitution, CancellationToken cancellationToken)
{
var mediaSources = GetStaticMediaSources(item, enablePathSubstitution, user);
diff --git a/Emby.Server.Implementations/Library/MediaStreamSelector.cs b/Emby.Server.Implementations/Library/MediaStreamSelector.cs
index 0a6c8845d..6b9f4d052 100644
--- a/Emby.Server.Implementations/Library/MediaStreamSelector.cs
+++ b/Emby.Server.Implementations/Library/MediaStreamSelector.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Linq;
diff --git a/Emby.Server.Implementations/Library/MusicManager.cs b/Emby.Server.Implementations/Library/MusicManager.cs
index 10602fea7..1ec578371 100644
--- a/Emby.Server.Implementations/Library/MusicManager.cs
+++ b/Emby.Server.Implementations/Library/MusicManager.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Linq;
@@ -89,10 +91,9 @@ namespace Emby.Server.Implementations.Library
Limit = 200,
- OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending) },
+ OrderBy = new[] { (ItemSortBy.Random, SortOrder.Ascending) },
DtoOptions = dtoOptions
-
});
}
diff --git a/Emby.Server.Implementations/Library/PathExtensions.cs b/Emby.Server.Implementations/Library/PathExtensions.cs
index d3a81f622..4fdf73b77 100644
--- a/Emby.Server.Implementations/Library/PathExtensions.cs
+++ b/Emby.Server.Implementations/Library/PathExtensions.cs
@@ -3,6 +3,9 @@ using System.Text.RegularExpressions;
namespace Emby.Server.Implementations.Library
{
+ /// <summary>
+ /// Class providing extension methods for working with paths.
+ /// </summary>
public static class PathExtensions
{
/// <summary>
@@ -32,6 +35,7 @@ namespace Emby.Server.Implementations.Library
int end = str.IndexOf(']', start);
return str.Substring(start, end - start);
}
+
// for imdbid we also accept pattern matching
if (string.Equals(attrib, "imdbid", StringComparison.OrdinalIgnoreCase))
{
diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs
index e39192d28..9d4bd9e59 100644
--- a/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/Audio/AudioResolver.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.IO;
@@ -13,7 +15,7 @@ using MediaBrowser.Model.IO;
namespace Emby.Server.Implementations.Library.Resolvers.Audio
{
/// <summary>
- /// Class AudioResolver
+ /// Class AudioResolver.
/// </summary>
public class AudioResolver : ItemResolver<MediaBrowser.Controller.Entities.Audio.Audio>, IMultiItemResolver
{
diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
index 3ce1da81a..4a2d210d5 100644
--- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
@@ -13,7 +13,7 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library.Resolvers.Audio
{
/// <summary>
- /// Class MusicAlbumResolver
+ /// Class MusicAlbumResolver.
/// </summary>
public class MusicAlbumResolver : ItemResolver<MusicAlbum>
{
@@ -21,6 +21,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
private readonly IFileSystem _fileSystem;
private readonly ILibraryManager _libraryManager;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MusicAlbumResolver"/> class.
+ /// </summary>
+ /// <param name="logger">The logger.</param>
+ /// <param name="fileSystem">The file system.</param>
+ /// <param name="libraryManager">The library manager.</param>
public MusicAlbumResolver(ILogger logger, IFileSystem fileSystem, ILibraryManager libraryManager)
{
_logger = logger;
@@ -50,16 +56,25 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
return null;
}
- if (!args.IsDirectory) return null;
+ if (!args.IsDirectory)
+ {
+ return null;
+ }
// Avoid mis-identifying top folders
- if (args.HasParent<MusicAlbum>()) return null;
- if (args.Parent.IsRoot) return null;
+ if (args.HasParent<MusicAlbum>())
+ {
+ return null;
+ }
+
+ if (args.Parent.IsRoot)
+ {
+ return null;
+ }
return IsMusicAlbum(args) ? new MusicAlbum() : null;
}
-
/// <summary>
/// Determine if the supplied file data points to a music album
/// </summary>
@@ -78,8 +93,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
// Args points to an album if parent is an Artist folder or it directly contains music
if (args.IsDirectory)
{
- //if (args.Parent is MusicArtist) return true; //saves us from testing children twice
- if (ContainsMusic(args.FileSystemChildren, true, args.DirectoryService, _logger, _fileSystem, args.GetLibraryOptions(), _libraryManager)) return true;
+ // if (args.Parent is MusicArtist) return true; //saves us from testing children twice
+ if (ContainsMusic(args.FileSystemChildren, true, args.DirectoryService, _logger, _fileSystem, args.GetLibraryOptions(), _libraryManager))
+ {
+ return true;
+ }
}
return false;
@@ -88,7 +106,8 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
/// <summary>
/// Determine if the supplied list contains what we should consider music
/// </summary>
- private bool ContainsMusic(IEnumerable<FileSystemMetadata> list,
+ private bool ContainsMusic(
+ IEnumerable<FileSystemMetadata> list,
bool allowSubfolders,
IDirectoryService directoryService,
ILogger logger,
diff --git a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
index 74e9b8304..ee7e84929 100644
--- a/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
@@ -11,7 +11,7 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library.Resolvers.Audio
{
/// <summary>
- /// Class MusicArtistResolver
+ /// Class MusicArtistResolver.
/// </summary>
public class MusicArtistResolver : ItemResolver<MusicArtist>
{
@@ -20,6 +20,13 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
private readonly ILibraryManager _libraryManager;
private readonly IServerConfigurationManager _config;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MusicArtistResolver"/> class.
+ /// </summary>
+ /// <param name="logger">The logger.</param>
+ /// <param name="fileSystem">The file system.</param>
+ /// <param name="libraryManager">The library manager.</param>
+ /// <param name="config">The configuration manager.</param>
public MusicArtistResolver(ILogger logger, IFileSystem fileSystem, ILibraryManager libraryManager, IServerConfigurationManager config)
{
_logger = logger;
@@ -41,7 +48,10 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
/// <returns>MusicArtist.</returns>
protected override MusicArtist Resolve(ItemResolveArgs args)
{
- if (!args.IsDirectory) return null;
+ if (!args.IsDirectory)
+ {
+ return null;
+ }
// Don't allow nested artists
if (args.HasParent<MusicArtist>() || args.HasParent<MusicAlbum>())
@@ -79,6 +89,5 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
// If we contain an album assume we are an artist folder
return args.FileSystemChildren.Where(i => i.IsDirectory).Any(i => albumResolver.IsMusicAlbum(i.FullName, directoryService, args.GetLibraryOptions())) ? new MusicArtist() : null;
}
-
}
}
diff --git a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs
index 541b13cbe..c4bb861b8 100644
--- a/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/BaseVideoResolver.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.IO;
using System.Linq;
@@ -10,7 +12,7 @@ using MediaBrowser.Model.Entities;
namespace Emby.Server.Implementations.Library.Resolvers
{
/// <summary>
- /// Resolves a Path into a Video or Video subclass
+ /// Resolves a Path into a Video or Video subclass.
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class BaseVideoResolver<T> : MediaBrowser.Controller.Resolvers.ItemResolver<T>
diff --git a/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs
index f22554ee5..0b93ebeb8 100644
--- a/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/Books/BookResolver.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.IO;
using System.Linq;
@@ -7,18 +9,10 @@ using MediaBrowser.Model.Entities;
namespace Emby.Server.Implementations.Library.Resolvers.Books
{
- /// <summary>
- ///
- /// </summary>
public class BookResolver : MediaBrowser.Controller.Resolvers.ItemResolver<Book>
{
private readonly string[] _validExtensions = { ".pdf", ".epub", ".mobi", ".cbr", ".cbz", ".azw3" };
- /// <summary>
- ///
- /// </summary>
- /// <param name="args"></param>
- /// <returns></returns>
protected override Book Resolve(ItemResolveArgs args)
{
var collectionType = args.GetCollectionType();
@@ -47,11 +41,6 @@ namespace Emby.Server.Implementations.Library.Resolvers.Books
return null;
}
- /// <summary>
- ///
- /// </summary>
- /// <param name="args"></param>
- /// <returns></returns>
private Book GetBook(ItemResolveArgs args)
{
var bookFiles = args.FileSystemChildren.Where(f =>
diff --git a/Emby.Server.Implementations/Library/Resolvers/FolderResolver.cs b/Emby.Server.Implementations/Library/Resolvers/FolderResolver.cs
index e48b6c967..7dbce7a6e 100644
--- a/Emby.Server.Implementations/Library/Resolvers/FolderResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/FolderResolver.cs
@@ -5,7 +5,7 @@ using MediaBrowser.Controller.Resolvers;
namespace Emby.Server.Implementations.Library.Resolvers
{
/// <summary>
- /// Class FolderResolver
+ /// Class FolderResolver.
/// </summary>
public class FolderResolver : FolderResolver<Folder>
{
@@ -32,7 +32,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
}
/// <summary>
- /// Class FolderResolver
+ /// Class FolderResolver.
/// </summary>
/// <typeparam name="TItemType">The type of the T item type.</typeparam>
public abstract class FolderResolver<TItemType> : ItemResolver<TItemType>
diff --git a/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs b/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs
index a6db40714..32ccc7fdd 100644
--- a/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/ItemResolver.cs
@@ -5,7 +5,7 @@ using MediaBrowser.Controller.Resolvers;
namespace Emby.Server.Implementations.Library.Resolvers
{
/// <summary>
- /// Class ItemResolver
+ /// Class ItemResolver.
/// </summary>
/// <typeparam name="T"></typeparam>
public abstract class ItemResolver<T> : IItemResolver
diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs
index 922bd4bbb..e4bc4a469 100644
--- a/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/Movies/BoxSetResolver.cs
@@ -4,12 +4,11 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Extensions;
namespace Emby.Server.Implementations.Library.Resolvers.Movies
{
/// <summary>
- /// Class BoxSetResolver
+ /// Class BoxSetResolver.
/// </summary>
public class BoxSetResolver : FolderResolver<BoxSet>
{
@@ -63,7 +62,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
/// <param name="item">The item.</param>
private static void SetProviderIdFromPath(BaseItem item)
{
- //we need to only look at the name of this actual item (not parents)
+ // we need to only look at the name of this actual item (not parents)
var justName = Path.GetFileName(item.Path);
var id = justName.GetAttributeValue("tmdbid");
diff --git a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
index 1b63b00a3..6c7690055 100644
--- a/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs
@@ -17,7 +17,7 @@ using MediaBrowser.Model.IO;
namespace Emby.Server.Implementations.Library.Resolvers.Movies
{
/// <summary>
- /// Class MovieResolver
+ /// Class MovieResolver.
/// </summary>
public class MovieResolver : BaseVideoResolver<Video>, IMultiItemResolver
{
@@ -27,6 +27,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
/// <value>The priority.</value>
public override ResolverPriority Priority => ResolverPriority.Third;
+ /// <inheritdoc />
public MultiItemResolverResult ResolveMultiple(
Folder parent,
List<FileSystemMetadata> files,
@@ -522,7 +523,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
CollectionType.MusicVideos,
CollectionType.Movies,
CollectionType.Photos
- };
+ };
private bool IsInvalid(Folder parent, string collectionType)
{
@@ -544,6 +545,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.Movies
private IImageProcessor _imageProcessor;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MovieResolver"/> class.
+ /// </summary>
+ /// <param name="libraryManager">The library manager.</param>
+ /// <param name="imageProcessor">The image processor.</param>
public MovieResolver(ILibraryManager libraryManager, IImageProcessor imageProcessor)
: base(libraryManager)
{
diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs
index 82779f8d3..4536b0aaa 100644
--- a/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/PhotoAlbumResolver.cs
@@ -7,11 +7,19 @@ using MediaBrowser.Model.Entities;
namespace Emby.Server.Implementations.Library.Resolvers
{
+ /// <summary>
+ /// Class PhotoAlbumResolver.
+ /// </summary>
public class PhotoAlbumResolver : FolderResolver<PhotoAlbum>
{
private readonly IImageProcessor _imageProcessor;
private ILibraryManager _libraryManager;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="PhotoAlbumResolver"/> class.
+ /// </summary>
+ /// <param name="imageProcessor">The image processor.</param>
+ /// <param name="libraryManager">The library manager.</param>
public PhotoAlbumResolver(IImageProcessor imageProcessor, ILibraryManager libraryManager)
{
_imageProcessor = imageProcessor;
@@ -74,9 +82,11 @@ namespace Emby.Server.Implementations.Library.Resolvers
}
}
}
+
return false;
}
+ /// <inheritdoc />
public override ResolverPriority Priority => ResolverPriority.Second;
}
}
diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs
index 8171c010b..a71ae8250 100644
--- a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.IO;
diff --git a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs
index c295894d3..a68562fc2 100644
--- a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs
@@ -1,10 +1,11 @@
+#pragma warning disable CS1591
+
using System;
using System.IO;
using System.Linq;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Playlists;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Extensions;
namespace Emby.Server.Implementations.Library.Resolvers
{
diff --git a/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs b/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs
index 7e4b38b4c..1030ed39d 100644
--- a/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/SpecialFolderResolver.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.IO;
using System.Linq;
diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs
index a6d18c9b5..7f477a0f0 100644
--- a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs
@@ -7,7 +7,7 @@ using MediaBrowser.Model.Entities;
namespace Emby.Server.Implementations.Library.Resolvers.TV
{
/// <summary>
- /// Class EpisodeResolver
+ /// Class EpisodeResolver.
/// </summary>
public class EpisodeResolver : BaseVideoResolver<Episode>
{
@@ -26,6 +26,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
}
var season = parent as Season;
+
// Just in case the user decided to nest episodes.
// Not officially supported but in some cases we can handle it.
if (season == null)
@@ -73,6 +74,10 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
return null;
}
+ /// <summary>
+ /// Initializes a new instance of the <see cref="EpisodeResolver"/> class.
+ /// </summary>
+ /// <param name="libraryManager">The library manager.</param>
public EpisodeResolver(ILibraryManager libraryManager)
: base(libraryManager)
{
diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
index 1f873d7c6..7cc9eabc8 100644
--- a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.IO;
@@ -14,7 +16,7 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library.Resolvers.TV
{
/// <summary>
- /// Class SeriesResolver
+ /// Class SeriesResolver.
/// </summary>
public class SeriesResolver : FolderResolver<Series>
{
@@ -22,6 +24,12 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
private readonly ILogger _logger;
private readonly ILibraryManager _libraryManager;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SeriesResolver"/> class.
+ /// </summary>
+ /// <param name="fileSystem">The file system.</param>
+ /// <param name="logger">The logger.</param>
+ /// <param name="libraryManager">The library manager.</param>
public SeriesResolver(IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager)
{
_fileSystem = fileSystem;
diff --git a/Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs
index 68d5d8b2d..62268fce9 100644
--- a/Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/VideoResolver.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs
index 6783b07eb..11d6c737a 100644
--- a/Emby.Server.Implementations/Library/SearchEngine.cs
+++ b/Emby.Server.Implementations/Library/SearchEngine.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Linq;
@@ -13,8 +15,6 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library
{
- /// <summary>
- /// </summary>
public class SearchEngine : ISearchEngine
{
private readonly ILibraryManager _libraryManager;
@@ -162,7 +162,7 @@ namespace Emby.Server.Implementations.Library
Limit = query.Limit,
IncludeItemsByName = string.IsNullOrEmpty(query.ParentId),
ParentId = string.IsNullOrEmpty(query.ParentId) ? Guid.Empty : new Guid(query.ParentId),
- OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending) },
+ OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) },
Recursive = true,
IsKids = query.IsKids,
diff --git a/Emby.Server.Implementations/Library/UserDataManager.cs b/Emby.Server.Implementations/Library/UserDataManager.cs
index 36adc0b9c..071681b08 100644
--- a/Emby.Server.Implementations/Library/UserDataManager.cs
+++ b/Emby.Server.Implementations/Library/UserDataManager.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -15,7 +17,7 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library
{
/// <summary>
- /// Class UserDataManager
+ /// Class UserDataManager.
/// </summary>
public class UserDataManager : IUserDataManager
{
@@ -55,6 +57,7 @@ namespace Emby.Server.Implementations.Library
{
throw new ArgumentNullException(nameof(userData));
}
+
if (item == null)
{
throw new ArgumentNullException(nameof(item));
@@ -160,11 +163,6 @@ namespace Emby.Server.Implementations.Library
return GetUserData(user, item.Id, item.GetUserDataKeys());
}
- public UserItemData GetUserData(string userId, BaseItem item)
- {
- return GetUserData(new Guid(userId), item);
- }
-
public UserItemData GetUserData(Guid userId, BaseItem item)
{
return GetUserData(userId, item.Id, item.GetUserDataKeys());
@@ -228,24 +226,21 @@ namespace Emby.Server.Implementations.Library
{
var pctIn = decimal.Divide(positionTicks, runtimeTicks) * 100;
- // Don't track in very beginning
if (pctIn < _config.Configuration.MinResumePct)
{
+ // ignore progress during the beginning
positionTicks = 0;
}
-
- // If we're at the end, assume completed
else if (pctIn > _config.Configuration.MaxResumePct || positionTicks >= runtimeTicks)
{
+ // mark as completed close to the end
positionTicks = 0;
data.Played = playedToCompletion = true;
}
-
else
{
// Enforce MinResumeDuration
var durationSeconds = TimeSpan.FromTicks(runtimeTicks).TotalSeconds;
-
if (durationSeconds < _config.Configuration.MinResumeDurationSeconds)
{
positionTicks = 0;
@@ -265,6 +260,7 @@ namespace Emby.Server.Implementations.Library
positionTicks = 0;
data.Played = false;
}
+
if (!item.SupportsPositionTicksResume)
{
positionTicks = 0;
diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs
index 2b22129f3..1b9c317d8 100644
--- a/Emby.Server.Implementations/Library/UserManager.cs
+++ b/Emby.Server.Implementations/Library/UserManager.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -36,19 +38,19 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library
{
/// <summary>
- /// Class UserManager
+ /// Class UserManager.
/// </summary>
public class UserManager : IUserManager
{
+ private readonly object _policySyncLock = new object();
+ private readonly object _configSyncLock = new object();
/// <summary>
- /// The _logger
+ /// The logger.
/// </summary>
private readonly ILogger _logger;
- private readonly object _policySyncLock = new object();
-
/// <summary>
- /// Gets the active user repository
+ /// Gets the active user repository.
/// </summary>
/// <value>The user repository.</value>
private readonly IUserRepository _userRepository;
@@ -194,10 +196,6 @@ namespace Emby.Server.Implementations.Library
return user;
}
- /// <inheritdoc />
- public User GetUserById(string id)
- => GetUserById(new Guid(id));
-
public User GetUserByName(string name)
{
if (string.IsNullOrWhiteSpace(name))
@@ -257,7 +255,12 @@ namespace Emby.Server.Implementations.Library
return builder.ToString();
}
- public async Task<User> AuthenticateUser(string username, string password, string hashedPassword, string remoteEndPoint, bool isUserSession)
+ public async Task<User> AuthenticateUser(
+ string username,
+ string password,
+ string hashedPassword,
+ string remoteEndPoint,
+ bool isUserSession)
{
if (string.IsNullOrWhiteSpace(username))
{
@@ -358,6 +361,8 @@ namespace Emby.Server.Implementations.Library
return success ? user : null;
}
+#nullable enable
+
private static string GetAuthenticationProviderId(IAuthenticationProvider provider)
{
return provider.GetType().FullName;
@@ -378,7 +383,7 @@ namespace Emby.Server.Implementations.Library
return GetPasswordResetProviders(user)[0];
}
- private IAuthenticationProvider[] GetAuthenticationProviders(User user)
+ private IAuthenticationProvider[] GetAuthenticationProviders(User? user)
{
var authenticationProviderId = user?.Policy.AuthenticationProviderId;
@@ -392,14 +397,14 @@ namespace Emby.Server.Implementations.Library
if (providers.Length == 0)
{
// Assign the user to the InvalidAuthProvider since no configured auth provider was valid/found
- _logger.LogWarning("User {UserName} was found with invalid/missing Authentication Provider {AuthenticationProviderId}. Assigning user to InvalidAuthProvider until this is corrected", user.Name, user.Policy.AuthenticationProviderId);
+ _logger.LogWarning("User {UserName} was found with invalid/missing Authentication Provider {AuthenticationProviderId}. Assigning user to InvalidAuthProvider until this is corrected", user?.Name, user?.Policy.AuthenticationProviderId);
providers = new IAuthenticationProvider[] { _invalidAuthProvider };
}
return providers;
}
- private IPasswordResetProvider[] GetPasswordResetProviders(User user)
+ private IPasswordResetProvider[] GetPasswordResetProviders(User? user)
{
var passwordResetProviderId = user?.Policy.PasswordResetProviderId;
@@ -418,7 +423,11 @@ namespace Emby.Server.Implementations.Library
return providers;
}
- private async Task<(string username, bool success)> AuthenticateWithProvider(IAuthenticationProvider provider, string username, string password, User resolvedUser)
+ private async Task<(string username, bool success)> AuthenticateWithProvider(
+ IAuthenticationProvider provider,
+ string username,
+ string password,
+ User? resolvedUser)
{
try
{
@@ -442,15 +451,15 @@ namespace Emby.Server.Implementations.Library
}
}
- private async Task<(IAuthenticationProvider authenticationProvider, string username, bool success)> AuthenticateLocalUser(
+ private async Task<(IAuthenticationProvider? authenticationProvider, string username, bool success)> AuthenticateLocalUser(
string username,
string password,
string hashedPassword,
- User user,
+ User? user,
string remoteEndPoint)
{
bool success = false;
- IAuthenticationProvider authenticationProvider = null;
+ IAuthenticationProvider? authenticationProvider = null;
foreach (var provider in GetAuthenticationProviders(user))
{
@@ -468,7 +477,7 @@ namespace Emby.Server.Implementations.Library
if (!success
&& _networkManager.IsInLocalNetwork(remoteEndPoint)
- && user.Configuration.EnableLocalPassword
+ && user?.Configuration.EnableLocalPassword == true
&& !string.IsNullOrEmpty(user.EasyPassword))
{
// Check easy password
@@ -547,6 +556,8 @@ namespace Emby.Server.Implementations.Library
_users[user.Id] = user;
}
+#nullable restore
+
public UserDto GetUserDto(User user, string remoteEndPoint = null)
{
if (user == null)
@@ -748,13 +759,10 @@ namespace Emby.Server.Implementations.Library
return user;
}
- /// <summary>
- /// Deletes the user.
- /// </summary>
- /// <param name="user">The user.</param>
- /// <returns>Task.</returns>
- /// <exception cref="ArgumentNullException">user</exception>
- /// <exception cref="ArgumentException"></exception>
+ /// <inheritdoc />
+ /// <exception cref="ArgumentNullException">The <c>user</c> is <c>null</c>.</exception>
+ /// <exception cref="ArgumentException">The <c>user</c> doesn't exist, or is the last administrator.</exception>
+ /// <exception cref="InvalidOperationException">The <c>user</c> can't be deleted; there are no other users.</exception>
public void DeleteUser(User user)
{
if (user == null)
@@ -773,7 +781,7 @@ namespace Emby.Server.Implementations.Library
if (_users.Count == 1)
{
- throw new ArgumentException(string.Format(
+ throw new InvalidOperationException(string.Format(
CultureInfo.InvariantCulture,
"The user '{0}' cannot be deleted because there must be at least one user in the system.",
user.Name));
@@ -794,17 +802,20 @@ namespace Emby.Server.Implementations.Library
_userRepository.DeleteUser(user);
- try
- {
- _fileSystem.DeleteFile(configPath);
- }
- catch (IOException ex)
+ // Delete user config dir
+ lock (_configSyncLock)
+ lock (_policySyncLock)
{
- _logger.LogError(ex, "Error deleting file {path}", configPath);
+ try
+ {
+ Directory.Delete(user.ConfigurationDirectoryPath, true);
+ }
+ catch (IOException ex)
+ {
+ _logger.LogError(ex, "Error deleting user config dir: {Path}", user.ConfigurationDirectoryPath);
+ }
}
- DeleteUserPolicy(user);
-
_users.TryRemove(user.Id, out _);
OnUserDeleted(user);
@@ -912,10 +923,9 @@ namespace Emby.Server.Implementations.Library
public UserPolicy GetUserPolicy(User user)
{
var path = GetPolicyFilePath(user);
-
if (!File.Exists(path))
{
- return GetDefaultPolicy(user);
+ return GetDefaultPolicy();
}
try
@@ -925,19 +935,15 @@ namespace Emby.Server.Implementations.Library
return (UserPolicy)_xmlSerializer.DeserializeFromFile(typeof(UserPolicy), path);
}
}
- catch (IOException)
- {
- return GetDefaultPolicy(user);
- }
catch (Exception ex)
{
- _logger.LogError(ex, "Error reading policy file: {path}", path);
+ _logger.LogError(ex, "Error reading policy file: {Path}", path);
- return GetDefaultPolicy(user);
+ return GetDefaultPolicy();
}
}
- private static UserPolicy GetDefaultPolicy(User user)
+ private static UserPolicy GetDefaultPolicy()
{
return new UserPolicy
{
@@ -977,27 +983,6 @@ namespace Emby.Server.Implementations.Library
}
}
- private void DeleteUserPolicy(User user)
- {
- var path = GetPolicyFilePath(user);
-
- try
- {
- lock (_policySyncLock)
- {
- _fileSystem.DeleteFile(path);
- }
- }
- catch (IOException)
- {
-
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error deleting policy file");
- }
- }
-
private static string GetPolicyFilePath(User user)
{
return Path.Combine(user.ConfigurationDirectoryPath, "policy.xml");
@@ -1024,19 +1009,14 @@ namespace Emby.Server.Implementations.Library
return (UserConfiguration)_xmlSerializer.DeserializeFromFile(typeof(UserConfiguration), path);
}
}
- catch (IOException)
- {
- return new UserConfiguration();
- }
catch (Exception ex)
{
- _logger.LogError(ex, "Error reading policy file: {path}", path);
+ _logger.LogError(ex, "Error reading policy file: {Path}", path);
return new UserConfiguration();
}
}
- private readonly object _configSyncLock = new object();
public void UpdateConfiguration(Guid userId, UserConfiguration config)
{
var user = GetUserById(userId);
diff --git a/Emby.Server.Implementations/Library/UserViewManager.cs b/Emby.Server.Implementations/Library/UserViewManager.cs
index 9c9977642..322819b05 100644
--- a/Emby.Server.Implementations/Library/UserViewManager.cs
+++ b/Emby.Server.Implementations/Library/UserViewManager.cs
@@ -1,3 +1,5 @@
+#pragma warning disable CS1591
+
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -340,7 +342,7 @@ namespace Emby.Server.Implementations.Library
var query = new InternalItemsQuery(user)
{
IncludeItemTypes = includeItemTypes,
- OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.DateCreated, SortOrder.Descending) },
+ OrderBy = new[] { (ItemSortBy.DateCreated, SortOrder.Descending) },
IsFolder = includeItemTypes.Length == 0 ? false : (bool?)null,
ExcludeItemTypes = excludeItemTypes,
IsVirtualItem = false,
diff --git a/Emby.Server.Implementations/Library/Validators/ArtistsPostScanTask.cs b/Emby.Server.Implementations/Library/Validators/ArtistsPostScanTask.cs
index 27261d449..61a07d0d6 100644
--- a/Emby.Server.Implementations/Library/Validators/ArtistsPostScanTask.cs
+++ b/Emby.Server.Implementations/Library/Validators/ArtistsPostScanTask.cs
@@ -8,12 +8,12 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library.Validators
{
/// <summary>
- /// Class ArtistsPostScanTask
+ /// Class ArtistsPostScanTask.
/// </summary>
public class ArtistsPostScanTask : ILibraryPostScanTask
{
/// <summary>
- /// The _library manager
+ /// The _library manager.
/// </summary>
private readonly ILibraryManager _libraryManager;
private readonly ILogger _logger;
@@ -23,6 +23,8 @@ namespace Emby.Server.Implementations.Library.Validators
/// Initializes a new instance of the <see cref="ArtistsPostScanTask" /> class.
/// </summary>
/// <param name="libraryManager">The library manager.</param>
+ /// <param name="logger">The logger.</param>
+ /// <param name="itemRepo">The item repository.</param>
public ArtistsPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
{
_libraryManager = libraryManager;
diff --git a/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs b/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs
index d06cda177..1497f4a3a 100644
--- a/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs
+++ b/Emby.Server.Implementations/Library/Validators/ArtistsValidator.cs
@@ -12,17 +12,17 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library.Validators
{
/// <summary>
- /// Class ArtistsValidator
+ /// Class ArtistsValidator.
/// </summary>
public class ArtistsValidator
{
/// <summary>
- /// The _library manager
+ /// The library manager.
/// </summary>
private readonly ILibraryManager _libraryManager;
/// <summary>
- /// The _logger
+ /// The logger.
/// </summary>
private readonly ILogger _logger;
private readonly IItemRepository _itemRepo;
diff --git a/Emby.Server.Implementations/Library/Validators/GenresPostScanTask.cs b/Emby.Server.Implementations/Library/Validators/GenresPostScanTask.cs
index 3bc5c2fb2..06d1dd89d 100644
--- a/Emby.Server.Implementations/Library/Validators/GenresPostScanTask.cs
+++ b/Emby.Server.Implementations/Library/Validators/GenresPostScanTask.cs
@@ -7,6 +7,9 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library.Validators
{
+ /// <summary>
+ /// Class GenresPostScanTask.
+ /// </summary>
public class GenresPostScanTask : ILibraryPostScanTask
{
/// <summary>
diff --git a/Emby.Server.Implementations/Library/Validators/GenresValidator.cs b/Emby.Server.Implementations/Library/Validators/GenresValidator.cs
index f8459c61f..b0cd5f87a 100644
--- a/Emby.Server.Implementations/Library/Validators/GenresValidator.cs
+++ b/Emby.Server.Implementations/Library/Validators/GenresValidator.cs
@@ -7,19 +7,28 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library.Validators
{
- class GenresValidator
+ /// <summary>
+ /// Class GenresValidator.
+ /// </summary>
+ public class GenresValidator
{
/// <summary>
- /// The _library manager
+ /// The library manager.
/// </summary>
private readonly ILibraryManager _libraryManager;
private readonly IItemRepository _itemRepo;
/// <summary>
- /// The _logger
+ /// The logger.
/// </summary>
private readonly ILogger _logger;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="GenresValidator"/> class.
+ /// </summary>
+ /// <param name="libraryManager">The library manager.</param>
+ /// <param name="logger">The logger.</param>
+ /// <param name="itemRepo">The item repository.</param>
public GenresValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
{
_libraryManager = libraryManager;
diff --git a/Emby.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs b/Emby.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs
index 9ac4bf761..58549e9d7 100644
--- a/Emby.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs
+++ b/Emby.Server.Implementations/Library/Validators/MusicGenresPostScanTask.cs
@@ -8,12 +8,12 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library.Validators
{
/// <summary>
- /// Class MusicGenresPostScanTask
+ /// Class MusicGenresPostScanTask.
/// </summary>
public class MusicGenresPostScanTask : ILibraryPostScanTask
{
/// <summary>
- /// The _library manager
+ /// The library manager.
/// </summary>
private readonly ILibraryManager _libraryManager;
private readonly ILogger _logger;
diff --git a/Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs b/Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs
index 710e5d043..5ee4ca72e 100644
--- a/Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs
+++ b/Emby.Server.Implementations/Library/Validators/MusicGenresValidator.cs
@@ -7,19 +7,28 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library.Validators
{
- class MusicGenresValidator
+ /// <summary>
+ /// Class MusicGenresValidator.
+ /// </summary>
+ public class MusicGenresValidator
{
/// <summary>
- /// The _library manager
+ /// The library manager.
/// </summary>
private readonly ILibraryManager _libraryManager;
/// <summary>
- /// The _logger
+ /// The logger.
/// </summary>
private readonly ILogger _logger;
private readonly IItemRepository _itemRepo;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MusicGenresValidator" /> class.
+ /// </summary>
+ /// <param name="libraryManager">The library manager.</param>
+ /// <param name="logger">The logger.</param>
+ /// <param name="itemRepo">The item repository.</param>
public MusicGenresValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
{
_libraryManager = libraryManager;
diff --git a/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs b/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs
index 137a010ec..8275c873a 100644
--- a/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs
+++ b/Emby.Server.Implementations/Library/Validators/PeopleValidator.cs
@@ -32,6 +32,7 @@ namespace Emby.Server.Implementations.Library.Validators
/// </summary>
/// <param name="libraryManager">The library manager.</param>
/// <param name="logger">The logger.</param>
+ /// <param name="fileSystem">The file system.</param>
public PeopleValidator(ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem)
{
_libraryManager = libraryManager;
diff --git a/Emby.Server.Implementations/Library/Validators/StudiosPostScanTask.cs b/Emby.Server.Implementations/Library/Validators/StudiosPostScanTask.cs
index 2efae0fe4..00899c336 100644
--- a/Emby.Server.Implementations/Library/Validators/StudiosPostScanTask.cs
+++ b/Emby.Server.Implementations/Library/Validators/StudiosPostScanTask.cs
@@ -8,12 +8,12 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library.Validators
{
/// <summary>
- /// Class MusicGenresPostScanTask
+ /// Class MusicGenresPostScanTask.
/// </summary>
public class StudiosPostScanTask : ILibraryPostScanTask
{
/// <summary>
- /// The _library manager
+ /// The _library manager.
/// </summary>
private readonly ILibraryManager _libraryManager;
@@ -25,7 +25,7 @@ namespace Emby.Server.Implementations.Library.Validators
/// </summary>
/// <param name="libraryManager">The library manager.</param>
/// <param name="logger">The logger.</param>
- /// <param name="itemRepo">Th item repository.</param>
+ /// <param name="itemRepo">The item repository.</param>
public StudiosPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
{
_libraryManager = libraryManager;
diff --git a/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs b/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs
index 93ded9e7b..15e7a0dbb 100644
--- a/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs
+++ b/Emby.Server.Implementations/Library/Validators/StudiosValidator.cs
@@ -9,19 +9,29 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Library.Validators
{
- class StudiosValidator
+ /// <summary>
+ /// Class StudiosValidator.
+ /// </summary>
+ public class StudiosValidator
{
/// <summary>
- /// The _library manager
+ /// The library manager.
/// </summary>
private readonly ILibraryManager _libraryManager;
private readonly IItemRepository _itemRepo;
+
/// <summary>
- /// The _logger
+ /// The logger.
/// </summary>
private readonly ILogger _logger;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="StudiosValidator" /> class.
+ /// </summary>
+ /// <param name="libraryManager">The library manager.</param>
+ /// <param name="logger">The logger.</param>
+ /// <param name="itemRepo">The item repository.</param>
public StudiosValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
{
_libraryManager = libraryManager;
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index 420209eda..f4d6cd4d3 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -1552,14 +1552,16 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
var episodesToDelete = librarySeries.GetItemList(
new InternalItemsQuery
{
- OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.DateCreated, SortOrder.Descending) },
+ OrderBy = new[] { (ItemSortBy.DateCreated, SortOrder.Descending) },
IsVirtualItem = false,
IsFolder = false,
Recursive = true,
DtoOptions = new DtoOptions(true)
- }).Where(i => i.IsFileProtocol && File.Exists(i.Path))
- .Skip(seriesTimer.KeepUpTo - 1)
- .ToList();
+
+ })
+ .Where(i => i.IsFileProtocol && File.Exists(i.Path))
+ .Skip(seriesTimer.KeepUpTo - 1)
+ .ToList();
foreach (var item in episodesToDelete)
{
@@ -1619,12 +1621,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
},
true);
}
- else
+ else if (File.Exists(timer.RecordingPath))
{
- if (File.Exists(timer.RecordingPath))
- {
- _fileSystem.DeleteFile(timer.RecordingPath);
- }
+ _fileSystem.DeleteFile(timer.RecordingPath);
}
_timerProvider.Delete(timer);
@@ -2188,7 +2187,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
},
MinStartDate = startDateUtc.AddMinutes(-3),
MaxStartDate = startDateUtc.AddMinutes(3),
- OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.StartDate, SortOrder.Ascending) }
+ OrderBy = new[] { (ItemSortBy.StartDate, SortOrder.Ascending) }
};
if (!string.IsNullOrWhiteSpace(channelId))
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
index 838ac97d7..1dd794da0 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
@@ -5,6 +5,7 @@ using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
+using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common;
@@ -12,7 +13,6 @@ using MediaBrowser.Common.Net;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Serialization;
@@ -663,7 +663,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
try
{
- return await _httpClient.SendAsync(options, "GET").ConfigureAwait(false);
+ return await _httpClient.SendAsync(options, HttpMethod.Get).ConfigureAwait(false);
}
catch (HttpException ex)
{
@@ -738,7 +738,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
httpOptions.RequestHeaders["token"] = token;
- using (await _httpClient.SendAsync(httpOptions, "PUT").ConfigureAwait(false))
+ using (await _httpClient.SendAsync(httpOptions, HttpMethod.Put).ConfigureAwait(false))
{
}
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs
index 88693f22a..1f38de2d8 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs
@@ -7,8 +7,8 @@ using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
-using Emby.XmlTv.Classes;
-using Emby.XmlTv.Entities;
+using Jellyfin.XmlTv;
+using Jellyfin.XmlTv.Entities;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
index d1f405679..e3f9df35a 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -212,16 +212,16 @@ namespace Emby.Server.Implementations.LiveTv
var orderBy = internalQuery.OrderBy.ToList();
- orderBy.AddRange(query.SortBy.Select(i => new ValueTuple<string, SortOrder>(i, query.SortOrder ?? SortOrder.Ascending)));
+ orderBy.AddRange(query.SortBy.Select(i => (i, query.SortOrder ?? SortOrder.Ascending)));
if (query.EnableFavoriteSorting)
{
- orderBy.Insert(0, new ValueTuple<string, SortOrder>(ItemSortBy.IsFavoriteOrLiked, SortOrder.Descending));
+ orderBy.Insert(0, (ItemSortBy.IsFavoriteOrLiked, SortOrder.Descending));
}
if (!internalQuery.OrderBy.Any(i => string.Equals(i.Item1, ItemSortBy.SortName, StringComparison.OrdinalIgnoreCase)))
{
- orderBy.Add(new ValueTuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending));
+ orderBy.Add((ItemSortBy.SortName, SortOrder.Ascending));
}
internalQuery.OrderBy = orderBy.ToArray();
@@ -307,9 +307,12 @@ namespace Emby.Server.Implementations.LiveTv
}
private ILiveTvService GetService(string name)
- {
- return _services.FirstOrDefault(i => string.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase));
- }
+ => Array.Find(_services, x => string.Equals(x.Name, name, StringComparison.OrdinalIgnoreCase))
+ ?? throw new KeyNotFoundException(
+ string.Format(
+ CultureInfo.InvariantCulture,
+ "No service with the name '{0}' can be found.",
+ name));
private static void Normalize(MediaSourceInfo mediaSource, ILiveTvService service, bool isVideo)
{
@@ -775,22 +778,22 @@ namespace Emby.Server.Implementations.LiveTv
var topFolder = GetInternalLiveTvFolder(cancellationToken);
- if (query.OrderBy.Length == 0)
+ if (query.OrderBy.Count == 0)
{
if (query.IsAiring ?? false)
{
// Unless something else was specified, order by start date to take advantage of a specialized index
- query.OrderBy = new ValueTuple<string, SortOrder>[]
+ query.OrderBy = new[]
{
- new ValueTuple<string, SortOrder>(ItemSortBy.StartDate, SortOrder.Ascending)
+ (ItemSortBy.StartDate, SortOrder.Ascending)
};
}
else
{
// Unless something else was specified, order by start date to take advantage of a specialized index
- query.OrderBy = new ValueTuple<string, SortOrder>[]
+ query.OrderBy = new[]
{
- new ValueTuple<string, SortOrder>(ItemSortBy.StartDate, SortOrder.Ascending)
+ (ItemSortBy.StartDate, SortOrder.Ascending)
};
}
}
@@ -874,7 +877,7 @@ namespace Emby.Server.Implementations.LiveTv
IsSports = query.IsSports,
IsKids = query.IsKids,
EnableTotalRecordCount = query.EnableTotalRecordCount,
- OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.StartDate, SortOrder.Ascending) },
+ OrderBy = new[] { (ItemSortBy.StartDate, SortOrder.Ascending) },
TopParentIds = new[] { topFolder.Id },
DtoOptions = options,
GenreIds = query.GenreIds
@@ -1399,7 +1402,7 @@ namespace Emby.Server.Implementations.LiveTv
IsVirtualItem = false,
Limit = limit,
StartIndex = query.StartIndex,
- OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.DateCreated, SortOrder.Descending) },
+ OrderBy = new[] { (ItemSortBy.DateCreated, SortOrder.Descending) },
EnableTotalRecordCount = query.EnableTotalRecordCount,
IncludeItemTypes = includeItemTypes.ToArray(),
ExcludeItemTypes = excludeItemTypes.ToArray(),
@@ -1897,7 +1900,7 @@ namespace Emby.Server.Implementations.LiveTv
MaxStartDate = now,
MinEndDate = now,
Limit = channelIds.Length,
- OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.StartDate, SortOrder.Ascending) },
+ OrderBy = new[] { (ItemSortBy.StartDate, SortOrder.Ascending) },
TopParentIds = new[] { GetInternalLiveTvFolder(CancellationToken.None).Id },
DtoOptions = options
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs
index 758495362..0d94f4b32 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Configuration;
@@ -64,7 +65,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
httpRequestOptions.RequestHeaders[header.Key] = header.Value;
}
- var response = await _httpClient.SendAsync(httpRequestOptions, "GET").ConfigureAwait(false);
+ var response = await _httpClient.SendAsync(httpRequestOptions, HttpMethod.Get).ConfigureAwait(false);
var extension = "ts";
var requiresRemux = false;
diff --git a/Emby.Server.Implementations/Localization/Core/af.json b/Emby.Server.Implementations/Localization/Core/af.json
new file mode 100644
index 000000000..dcec26801
--- /dev/null
+++ b/Emby.Server.Implementations/Localization/Core/af.json
@@ -0,0 +1,96 @@
+{
+ "Artists": "Kunstenare",
+ "Channels": "Kanale",
+ "Folders": "Fouers",
+ "Favorites": "Gunstelinge",
+ "HeaderFavoriteShows": "Gunsteling Vertonings",
+ "ValueSpecialEpisodeName": "Spesiaal - {0}",
+ "HeaderAlbumArtists": "Album Kunstenaars",
+ "Books": "Boeke",
+ "HeaderNextUp": "Volgende",
+ "Movies": "Rolprente",
+ "Shows": "Program",
+ "HeaderContinueWatching": "Hou Aan Kyk",
+ "HeaderFavoriteEpisodes": "Gunsteling Episodes",
+ "Photos": "Fotos",
+ "Playlists": "Speellysse",
+ "HeaderFavoriteArtists": "Gunsteling Kunstenaars",
+ "HeaderFavoriteAlbums": "Gunsteling Albums",
+ "Sync": "Sinkroniseer",
+ "HeaderFavoriteSongs": "Gunsteling Liedjies",
+ "Songs": "Liedjies",
+ "DeviceOnlineWithName": "{0} is verbind",
+ "DeviceOfflineWithName": "{0} het afgesluit",
+ "Collections": "Versamelings",
+ "Inherit": "Ontvang",
+ "HeaderLiveTV": "Live TV",
+ "Application": "Program",
+ "AppDeviceValues": "App: {0}, Toestel: {1}",
+ "VersionNumber": "Weergawe {0}",
+ "ValueHasBeenAddedToLibrary": "{0} is by jou media biblioteek bygevoeg",
+ "UserStoppedPlayingItemWithValues": "{0} het klaar {1} op {2} gespeel",
+ "UserStartedPlayingItemWithValues": "{0} is besig om {1} op {2} te speel",
+ "UserPolicyUpdatedWithName": "Gebruiker beleid is verander vir {0}",
+ "UserPasswordChangedWithName": "Gebruiker {0} se wagwoord is verander",
+ "UserOnlineFromDevice": "{0} is aanlyn van {1}",
+ "UserOfflineFromDevice": "{0} is ontkoppel van {1}",
+ "UserLockedOutWithName": "Gebruiker {0} is uitgesluit",
+ "UserDownloadingItemWithValues": "{0} is besig om {1} af te laai",
+ "UserDeletedWithName": "Gebruiker {0} is verwyder",
+ "UserCreatedWithName": "Gebruiker {0} is geskep",
+ "User": "Gebruiker",
+ "TvShows": "TV Programme",
+ "System": "Stelsel",
+ "SubtitlesDownloadedForItem": "Ondertitels afgelaai vir {0}",
+ "SubtitleDownloadFailureFromForItem": "Ondertitels het misluk om af te laai van {0} vir {1}",
+ "StartupEmbyServerIsLoading": "Jellyfin Bediener is besig om te laai. Probeer weer in 'n kort tyd.",
+ "ServerNameNeedsToBeRestarted": "{0} moet herbegin word",
+ "ScheduledTaskStartedWithName": "{0} het begin",
+ "ScheduledTaskFailedWithName": "{0} het misluk",
+ "ProviderValue": "Voorsiener: {0}",
+ "PluginUpdatedWithName": "{0} was opgedateer",
+ "PluginUninstalledWithName": "{0} was verwyder",
+ "PluginInstalledWithName": "{0} is geïnstalleer",
+ "Plugin": "Inprop module",
+ "NotificationOptionVideoPlaybackStopped": "Video terugspeel het gestop",
+ "NotificationOptionVideoPlayback": "Video terugspeel het begin",
+ "NotificationOptionUserLockedOut": "Gebruiker uitgeslyt",
+ "NotificationOptionTaskFailed": "Geskeduleerde taak het misluk",
+ "NotificationOptionServerRestartRequired": "Bediener herbegin nodig",
+ "NotificationOptionPluginUpdateInstalled": "Nuwe inprop module geïnstalleer",
+ "NotificationOptionPluginUninstalled": "Inprop module verwyder",
+ "NotificationOptionPluginInstalled": "Inprop module geïnstalleer",
+ "NotificationOptionPluginError": "Inprop module het misluk",
+ "NotificationOptionNewLibraryContent": "Nuwe inhoud bygevoeg",
+ "NotificationOptionInstallationFailed": "Installering het misluk",
+ "NotificationOptionCameraImageUploaded": "Kamera foto is opgelaai",
+ "NotificationOptionAudioPlaybackStopped": "Oudio terugspeel het gestop",
+ "NotificationOptionAudioPlayback": "Oudio terugspeel het begin",
+ "NotificationOptionApplicationUpdateInstalled": "Nuwe program weergawe geïnstalleer",
+ "NotificationOptionApplicationUpdateAvailable": "Nuwe program weergawe beskikbaar",
+ "NewVersionIsAvailable": "'n Nuwe Jellyfin Bedienaar weergawe kan afgelaai word.",
+ "NameSeasonUnknown": "Seisoen Onbekend",
+ "NameSeasonNumber": "Seisoen {0}",
+ "NameInstallFailed": "{0} installering het misluk",
+ "MusicVideos": "Musiek videos",
+ "Music": "Musiek",
+ "MixedContent": "Gemengde inhoud",
+ "MessageServerConfigurationUpdated": "Bediener konfigurasie is opgedateer",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Bediener konfigurasie seksie {0} is opgedateer",
+ "MessageApplicationUpdatedTo": "Jellyfin Bediener is opgedateer na {0}",
+ "MessageApplicationUpdated": "Jellyfin Bediener is opgedateer",
+ "Latest": "Nuutste",
+ "LabelRunningTimeValue": "Lopende tyd: {0}",
+ "LabelIpAddressValue": "IP adres: {0}",
+ "ItemRemovedWithName": "{0} is uit versameling verwyder",
+ "ItemAddedWithName": "{0} is in die versameling",
+ "HomeVideos": "Tuis opnames",
+ "HeaderRecordingGroups": "Groep Opnames",
+ "HeaderCameraUploads": "Kamera Oplaai",
+ "Genres": "Genres",
+ "FailedLoginAttemptWithUserName": "Mislukte aansluiting van {0}",
+ "ChapterNameValue": "Hoofstuk",
+ "CameraImageUploadedFrom": "'n Nuwe kamera photo opgelaai van {0}",
+ "AuthenticationSucceededWithUserName": "{0} suksesvol geverifieer",
+ "Albums": "Albums"
+}
diff --git a/Emby.Server.Implementations/Localization/Core/bg-BG.json b/Emby.Server.Implementations/Localization/Core/bg-BG.json
index bfe32a6c2..46c10d912 100644
--- a/Emby.Server.Implementations/Localization/Core/bg-BG.json
+++ b/Emby.Server.Implementations/Localization/Core/bg-BG.json
@@ -5,13 +5,13 @@
"Artists": "Изпълнители",
"AuthenticationSucceededWithUserName": "{0} се удостовери успешно",
"Books": "Книги",
- "CameraImageUploadedFrom": "",
+ "CameraImageUploadedFrom": "Нова снимка от камера беше качена от {0}",
"Channels": "Канали",
"ChapterNameValue": "Глава {0}",
"Collections": "Колекции",
"DeviceOfflineWithName": "{0} се разкачи",
"DeviceOnlineWithName": "{0} е свързан",
- "FailedLoginAttemptWithUserName": "",
+ "FailedLoginAttemptWithUserName": "Неуспешен опит за влизане от {0}",
"Favorites": "Любими",
"Folders": "Папки",
"Genres": "Жанрове",
diff --git a/Emby.Server.Implementations/Localization/Core/ca.json b/Emby.Server.Implementations/Localization/Core/ca.json
index 74406a064..9961b0984 100644
--- a/Emby.Server.Implementations/Localization/Core/ca.json
+++ b/Emby.Server.Implementations/Localization/Core/ca.json
@@ -1,11 +1,11 @@
{
"Albums": "Àlbums",
- "AppDeviceValues": "App: {0}, Dispositiu: {1}",
- "Application": "Application",
+ "AppDeviceValues": "Aplicació: {0}, Dispositiu: {1}",
+ "Application": "Aplicació",
"Artists": "Artistes",
"AuthenticationSucceededWithUserName": "{0} s'ha autenticat correctament",
"Books": "Llibres",
- "CameraImageUploadedFrom": "A new camera image has been uploaded from {0}",
+ "CameraImageUploadedFrom": "Una nova imatge de càmera ha sigut pujada des de {0}",
"Channels": "Canals",
"ChapterNameValue": "Episodi {0}",
"Collections": "Col·leccions",
@@ -15,8 +15,8 @@
"Favorites": "Preferits",
"Folders": "Directoris",
"Genres": "Gèneres",
- "HeaderAlbumArtists": "Album Artists",
- "HeaderCameraUploads": "Camera Uploads",
+ "HeaderAlbumArtists": "Artistes dels Àlbums",
+ "HeaderCameraUploads": "Pujades de Càmera",
"HeaderContinueWatching": "Continua Veient",
"HeaderFavoriteAlbums": "Àlbums Preferits",
"HeaderFavoriteArtists": "Artistes Preferits",
@@ -27,71 +27,71 @@
"HeaderNextUp": "A continuació",
"HeaderRecordingGroups": "Grups d'Enregistrament",
"HomeVideos": "Vídeos domèstics",
- "Inherit": "Heretat",
- "ItemAddedWithName": "{0} afegit a la biblioteca",
- "ItemRemovedWithName": "{0} eliminat de la biblioteca",
+ "Inherit": "Hereta",
+ "ItemAddedWithName": "{0} ha estat afegit a la biblioteca",
+ "ItemRemovedWithName": "{0} ha estat eliminat de la biblioteca",
"LabelIpAddressValue": "Adreça IP: {0}",
- "LabelRunningTimeValue": "Temps en marxa: {0}",
+ "LabelRunningTimeValue": "Temps en funcionament: {0}",
"Latest": "Darreres",
- "MessageApplicationUpdated": "El Servidor d'Jellyfin ha estat actualitzat",
- "MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}",
- "MessageNamedServerConfigurationUpdatedWithValue": "La secció de configuració {0} ha estat actualitzada",
+ "MessageApplicationUpdated": "El Servidor de Jellyfin ha estat actualitzat",
+ "MessageApplicationUpdatedTo": "El Servidor de Jellyfin ha estat actualitzat a {0}",
+ "MessageNamedServerConfigurationUpdatedWithValue": "La secció {0} de la configuració del servidor ha estat actualitzada",
"MessageServerConfigurationUpdated": "S'ha actualitzat la configuració del servidor",
"MixedContent": "Contingut mesclat",
"Movies": "Pel·lícules",
"Music": "Música",
"MusicVideos": "Vídeos musicals",
- "NameInstallFailed": "{0} installation failed",
+ "NameInstallFailed": "Instalació de {0} fallida",
"NameSeasonNumber": "Temporada {0}",
- "NameSeasonUnknown": "Season Unknown",
- "NewVersionIsAvailable": "A new version of Jellyfin Server is available for download.",
+ "NameSeasonUnknown": "Temporada Desconeguda",
+ "NewVersionIsAvailable": "Una nova versió del Servidor Jellyfin està disponible per descarregar.",
"NotificationOptionApplicationUpdateAvailable": "Actualització d'aplicació disponible",
"NotificationOptionApplicationUpdateInstalled": "Actualització d'aplicació instal·lada",
- "NotificationOptionAudioPlayback": "Audio playback started",
- "NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
- "NotificationOptionCameraImageUploaded": "Camera image uploaded",
- "NotificationOptionInstallationFailed": "Installation failure",
- "NotificationOptionNewLibraryContent": "New content added",
- "NotificationOptionPluginError": "Un component ha fallat",
- "NotificationOptionPluginInstalled": "Complement instal·lat",
- "NotificationOptionPluginUninstalled": "Complement desinstal·lat",
- "NotificationOptionPluginUpdateInstalled": "Actualització de complement instal·lada",
- "NotificationOptionServerRestartRequired": "Server restart required",
- "NotificationOptionTaskFailed": "Scheduled task failure",
- "NotificationOptionUserLockedOut": "User locked out",
- "NotificationOptionVideoPlayback": "Video playback started",
- "NotificationOptionVideoPlaybackStopped": "Video playback stopped",
+ "NotificationOptionAudioPlayback": "Reproducció d'audio iniciada",
+ "NotificationOptionAudioPlaybackStopped": "Reproducció d'audio aturada",
+ "NotificationOptionCameraImageUploaded": "Imatge de càmera pujada",
+ "NotificationOptionInstallationFailed": "Instalació fallida",
+ "NotificationOptionNewLibraryContent": "Nou contingut afegit",
+ "NotificationOptionPluginError": "Un connector ha fallat",
+ "NotificationOptionPluginInstalled": "Connector instal·lat",
+ "NotificationOptionPluginUninstalled": "Connector desinstal·lat",
+ "NotificationOptionPluginUpdateInstalled": "Actualització de connector instal·lada",
+ "NotificationOptionServerRestartRequired": "Reinici del servidor requerit",
+ "NotificationOptionTaskFailed": "Tasca programada fallida",
+ "NotificationOptionUserLockedOut": "Usuari tancat",
+ "NotificationOptionVideoPlayback": "Reproducció de video iniciada",
+ "NotificationOptionVideoPlaybackStopped": "Reproducció de video aturada",
"Photos": "Fotos",
"Playlists": "Llistes de reproducció",
- "Plugin": "Plugin",
+ "Plugin": "Connector",
"PluginInstalledWithName": "{0} ha estat instal·lat",
"PluginUninstalledWithName": "{0} ha estat desinstal·lat",
"PluginUpdatedWithName": "{0} ha estat actualitzat",
"ProviderValue": "Proveïdor: {0}",
"ScheduledTaskFailedWithName": "{0} ha fallat",
"ScheduledTaskStartedWithName": "{0} iniciat",
- "ServerNameNeedsToBeRestarted": "{0} needs to be restarted",
- "Shows": "Espectacles",
+ "ServerNameNeedsToBeRestarted": "{0} necessita ser reiniciat",
+ "Shows": "Programes",
"Songs": "Cançons",
"StartupEmbyServerIsLoading": "El Servidor d'Jellyfin est&agrave; carregant. Si et plau, prova de nou en breus.",
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
- "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}",
+ "SubtitleDownloadFailureFromForItem": "Els subtítols no s'han pogut baixar de {0} per {1}",
"SubtitlesDownloadedForItem": "Subtítols descarregats per a {0}",
- "Sync": "Sync",
+ "Sync": "Sincronitzar",
"System": "System",
"TvShows": "Espectacles de TV",
"User": "User",
"UserCreatedWithName": "S'ha creat l'usuari {0}",
"UserDeletedWithName": "L'usuari {0} ha estat eliminat",
"UserDownloadingItemWithValues": "{0} està descarregant {1}",
- "UserLockedOutWithName": "User {0} has been locked out",
+ "UserLockedOutWithName": "L'usuari {0} ha sigut tancat",
"UserOfflineFromDevice": "{0} s'ha desconnectat de {1}",
"UserOnlineFromDevice": "{0} està connectat des de {1}",
"UserPasswordChangedWithName": "La contrasenya ha estat canviada per a l'usuari {0}",
- "UserPolicyUpdatedWithName": "User policy has been updated for {0}",
+ "UserPolicyUpdatedWithName": "La política d'usuari s'ha actualitzat per {0}",
"UserStartedPlayingItemWithValues": "{0} ha començat a reproduir {1}",
"UserStoppedPlayingItemWithValues": "{0} ha parat de reproduir {1}",
- "ValueHasBeenAddedToLibrary": "{0} has been added to your media library",
+ "ValueHasBeenAddedToLibrary": "{0} ha sigut afegit a la teva llibreria",
"ValueSpecialEpisodeName": "Especial - {0}",
"VersionNumber": "Versió {0}"
}
diff --git a/Emby.Server.Implementations/Localization/Core/de.json b/Emby.Server.Implementations/Localization/Core/de.json
index 12bc16d74..019736c47 100644
--- a/Emby.Server.Implementations/Localization/Core/de.json
+++ b/Emby.Server.Implementations/Localization/Core/de.json
@@ -3,14 +3,14 @@
"AppDeviceValues": "App: {0}, Gerät: {1}",
"Application": "Anwendung",
"Artists": "Interpreten",
- "AuthenticationSucceededWithUserName": "{0} hat sich angemeldet",
+ "AuthenticationSucceededWithUserName": "{0} hat sich erfolgreich angemeldet",
"Books": "Bücher",
"CameraImageUploadedFrom": "Ein neues Foto wurde hochgeladen von {0}",
"Channels": "Kanäle",
"ChapterNameValue": "Kapitel {0}",
"Collections": "Sammlungen",
"DeviceOfflineWithName": "{0} wurde getrennt",
- "DeviceOnlineWithName": "{0} hat sich verbunden",
+ "DeviceOnlineWithName": "{0} ist verbunden",
"FailedLoginAttemptWithUserName": "Fehlgeschlagener Anmeldeversuch von {0}",
"Favorites": "Favoriten",
"Folders": "Verzeichnisse",
diff --git a/Emby.Server.Implementations/Localization/Core/el.json b/Emby.Server.Implementations/Localization/Core/el.json
index 3589a4893..580b42330 100644
--- a/Emby.Server.Implementations/Localization/Core/el.json
+++ b/Emby.Server.Implementations/Localization/Core/el.json
@@ -3,7 +3,7 @@
"AppDeviceValues": "Εφαρμογή: {0}, Συσκευή: {1}",
"Application": "Εφαρμογή",
"Artists": "Καλλιτέχνες",
- "AuthenticationSucceededWithUserName": "Ο χρήστης {0} επαληθεύτηκε με επιτυχία",
+ "AuthenticationSucceededWithUserName": "Ο χρήστης {0} επαληθεύτηκε επιτυχώς",
"Books": "Βιβλία",
"CameraImageUploadedFrom": "Μια νέα εικόνα κάμερας έχει αποσταλεί από {0}",
"Channels": "Κανάλια",
diff --git a/Emby.Server.Implementations/Localization/Core/fr.json b/Emby.Server.Implementations/Localization/Core/fr.json
index 9805992be..e1dce82ff 100644
--- a/Emby.Server.Implementations/Localization/Core/fr.json
+++ b/Emby.Server.Implementations/Localization/Core/fr.json
@@ -19,10 +19,10 @@
"HeaderCameraUploads": "Photos transférées",
"HeaderContinueWatching": "Continuer à regarder",
"HeaderFavoriteAlbums": "Albums favoris",
- "HeaderFavoriteArtists": "Artistes favoris",
+ "HeaderFavoriteArtists": "Artistes préférés",
"HeaderFavoriteEpisodes": "Épisodes favoris",
"HeaderFavoriteShows": "Séries favorites",
- "HeaderFavoriteSongs": "Chansons favorites",
+ "HeaderFavoriteSongs": "Chansons préférées",
"HeaderLiveTV": "TV en direct",
"HeaderNextUp": "À suivre",
"HeaderRecordingGroups": "Groupes d'enregistrements",
diff --git a/Emby.Server.Implementations/Localization/Core/he.json b/Emby.Server.Implementations/Localization/Core/he.json
index 0ed998c4b..b08c8966e 100644
--- a/Emby.Server.Implementations/Localization/Core/he.json
+++ b/Emby.Server.Implementations/Localization/Core/he.json
@@ -1,41 +1,41 @@
{
"Albums": "אלבומים",
- "AppDeviceValues": "App: {0}, Device: {1}",
+ "AppDeviceValues": "יישום: {0}, מכשיר: {1}",
"Application": "אפליקציה",
"Artists": "אמנים",
- "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "AuthenticationSucceededWithUserName": "{0} זוהה בהצלחה",
"Books": "ספרים",
- "CameraImageUploadedFrom": "A new camera image has been uploaded from {0}",
- "Channels": "Channels",
- "ChapterNameValue": "Chapter {0}",
- "Collections": "Collections",
- "DeviceOfflineWithName": "{0} has disconnected",
- "DeviceOnlineWithName": "{0} is connected",
- "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
- "Favorites": "Favorites",
- "Folders": "Folders",
+ "CameraImageUploadedFrom": "תמונה חדשה הועלתה מ{0}",
+ "Channels": "ערוצים",
+ "ChapterNameValue": "פרק {0}",
+ "Collections": "קולקציות",
+ "DeviceOfflineWithName": "{0} התנתק",
+ "DeviceOnlineWithName": "{0} מחובר",
+ "FailedLoginAttemptWithUserName": "ניסיון כניסה שגוי מ{0}",
+ "Favorites": "אהובים",
+ "Folders": "תיקיות",
"Genres": "ז'אנרים",
- "HeaderAlbumArtists": "Album Artists",
- "HeaderCameraUploads": "Camera Uploads",
- "HeaderContinueWatching": "המשך בצפייה",
- "HeaderFavoriteAlbums": "Favorite Albums",
- "HeaderFavoriteArtists": "Favorite Artists",
- "HeaderFavoriteEpisodes": "Favorite Episodes",
- "HeaderFavoriteShows": "Favorite Shows",
- "HeaderFavoriteSongs": "Favorite Songs",
- "HeaderLiveTV": "Live TV",
- "HeaderNextUp": "Next Up",
+ "HeaderAlbumArtists": "אמני האלבום",
+ "HeaderCameraUploads": "העלאות ממצלמה",
+ "HeaderContinueWatching": "המשך לצפות",
+ "HeaderFavoriteAlbums": "אלבומים שאהבתי",
+ "HeaderFavoriteArtists": "אמנים שאהבתי",
+ "HeaderFavoriteEpisodes": "פרקים אהובים",
+ "HeaderFavoriteShows": "תוכניות אהובות",
+ "HeaderFavoriteSongs": "שירים שאהבתי",
+ "HeaderLiveTV": "טלוויזיה בשידור חי",
+ "HeaderNextUp": "הבא",
"HeaderRecordingGroups": "קבוצות הקלטה",
- "HomeVideos": "Home videos",
- "Inherit": "Inherit",
+ "HomeVideos": "סרטונים בייתים",
+ "Inherit": "הורש",
"ItemAddedWithName": "{0} was added to the library",
- "ItemRemovedWithName": "{0} was removed from the library",
- "LabelIpAddressValue": "Ip address: {0}",
- "LabelRunningTimeValue": "Running time: {0}",
+ "ItemRemovedWithName": "{0} נמחק מהספרייה",
+ "LabelIpAddressValue": "Ip כתובת: {0}",
+ "LabelRunningTimeValue": "משך צפייה: {0}",
"Latest": "אחרון",
- "MessageApplicationUpdated": "Jellyfin Server has been updated",
- "MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}",
- "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
+ "MessageApplicationUpdated": "שרת הJellyfin עודכן",
+ "MessageApplicationUpdatedTo": "שרת הJellyfin עודכן לגרסא {0}",
+ "MessageNamedServerConfigurationUpdatedWithValue": "הגדרת השרת {0} שונתה",
"MessageServerConfigurationUpdated": "Server configuration has been updated",
"MixedContent": "תוכן מעורב",
"Movies": "סרטים",
@@ -50,7 +50,7 @@
"NotificationOptionAudioPlayback": "Audio playback started",
"NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
"NotificationOptionCameraImageUploaded": "Camera image uploaded",
- "NotificationOptionInstallationFailed": "Installation failure",
+ "NotificationOptionInstallationFailed": "התקנה נכשלה",
"NotificationOptionNewLibraryContent": "New content added",
"NotificationOptionPluginError": "Plugin failure",
"NotificationOptionPluginInstalled": "Plugin installed",
diff --git a/Emby.Server.Implementations/Localization/Core/id.json b/Emby.Server.Implementations/Localization/Core/id.json
new file mode 100644
index 000000000..8d17ad38e
--- /dev/null
+++ b/Emby.Server.Implementations/Localization/Core/id.json
@@ -0,0 +1,32 @@
+{
+ "Albums": "Album",
+ "AuthenticationSucceededWithUserName": "{0} berhasil diautentikasi",
+ "AppDeviceValues": "Aplikasi: {0}, Alat: {1}",
+ "LabelRunningTimeValue": "Waktu berjalan: {0}",
+ "MessageApplicationUpdatedTo": "Jellyfin Server sudah diperbarui ke {0}",
+ "MessageApplicationUpdated": "Jellyfin Server sudah diperbarui",
+ "Latest": "Terbaru",
+ "LabelIpAddressValue": "IP address: {0}",
+ "ItemRemovedWithName": "{0} sudah dikeluarkan dari perpustakaan",
+ "ItemAddedWithName": "{0} sudah dimasukkan ke dalam perpustakaan",
+ "Inherit": "Warisan",
+ "HomeVideos": "Video Rumah",
+ "HeaderRecordingGroups": "Grup Rekaman",
+ "HeaderNextUp": "Selanjutnya",
+ "HeaderLiveTV": "TV Live",
+ "HeaderFavoriteSongs": "Lagu Favorit",
+ "HeaderFavoriteShows": "Tayangan Favorit",
+ "HeaderFavoriteEpisodes": "Episode Favorit",
+ "HeaderFavoriteArtists": "Artis Favorit",
+ "HeaderFavoriteAlbums": "Album Favorit",
+ "HeaderContinueWatching": "Masih Melihat",
+ "HeaderCameraUploads": "Uplod Kamera",
+ "HeaderAlbumArtists": "Album Artis",
+ "Genres": "Genre",
+ "Folders": "Folder",
+ "Favorites": "Favorit",
+ "Collections": "Koleksi",
+ "Books": "Buku",
+ "Artists": "Artis",
+ "Application": "Aplikasi"
+}
diff --git a/Emby.Server.Implementations/Localization/Core/is.json b/Emby.Server.Implementations/Localization/Core/is.json
new file mode 100644
index 000000000..c3b5211b8
--- /dev/null
+++ b/Emby.Server.Implementations/Localization/Core/is.json
@@ -0,0 +1,78 @@
+{
+ "LabelIpAddressValue": "IP tala: {0}",
+ "ItemRemovedWithName": "{0} var fjarlægt úr safninu",
+ "ItemAddedWithName": "{0} var bætt í safnið",
+ "Inherit": "Erfa",
+ "HomeVideos": "Myndbönd að heiman",
+ "HeaderRecordingGroups": "Upptökuhópar",
+ "HeaderNextUp": "Næst á dagskrá",
+ "HeaderLiveTV": "Sjónvarp í beinni útsendingu",
+ "HeaderFavoriteSongs": "Uppáhalds Lög",
+ "HeaderFavoriteShows": "Uppáhalds Sjónvarpsþættir",
+ "HeaderFavoriteEpisodes": "Uppáhalds Þættir",
+ "HeaderFavoriteArtists": "Uppáhalds Listamenn",
+ "HeaderFavoriteAlbums": "Uppáhalds Plötur",
+ "HeaderContinueWatching": "Halda áfram að horfa",
+ "HeaderCameraUploads": "Myndavéla upphal",
+ "HeaderAlbumArtists": "Höfundur plötu",
+ "Genres": "Tegundir",
+ "Folders": "Möppur",
+ "Favorites": "Uppáhalds",
+ "FailedLoginAttemptWithUserName": "{0} reyndi að auðkenna sig",
+ "DeviceOnlineWithName": "{0} hefur tengst",
+ "DeviceOfflineWithName": "{0} hefur aftengst",
+ "Collections": "Söfn",
+ "ChapterNameValue": "Kafli {0}",
+ "Channels": "Stöðvar",
+ "CameraImageUploadedFrom": "Ný ljósmynd frá myndavél hefur verið hlaðið upp frá {0}",
+ "Books": "Bækur",
+ "AuthenticationSucceededWithUserName": "{0} náði að auðkennast",
+ "Artists": "Listamaður",
+ "Application": "Forrit",
+ "AppDeviceValues": "Snjallforrit: {0}, Tæki: {1}",
+ "Albums": "Plötur",
+ "Plugin": "Viðbót",
+ "Photos": "Myndir",
+ "NotificationOptionVideoPlaybackStopped": "Myndbandafspilun stöðvuð",
+ "NotificationOptionVideoPlayback": "Myndbandafspilun hafin",
+ "NotificationOptionUserLockedOut": "Notandi læstur úti",
+ "NotificationOptionServerRestartRequired": "Endurræsing miðlara nauðsynileg",
+ "NotificationOptionPluginUpdateInstalled": "Viðbótar uppfærsla uppsett",
+ "NotificationOptionPluginUninstalled": "Viðbót fjarlægð",
+ "NotificationOptionPluginInstalled": "Viðbót settur upp",
+ "NotificationOptionPluginError": "Bilun í viðbót",
+ "NotificationOptionInstallationFailed": "Uppsetning tókst ekki",
+ "NotificationOptionCameraImageUploaded": "Myndavélarmynd hlaðið upp",
+ "NotificationOptionAudioPlaybackStopped": "Hljóðafspilun stöðvuð",
+ "NotificationOptionAudioPlayback": "Hljóðafspilun hafin",
+ "NotificationOptionApplicationUpdateInstalled": "Uppfærsla uppsett",
+ "NotificationOptionApplicationUpdateAvailable": "Uppfærsla í boði",
+ "NameSeasonUnknown": "Sería óþekkt",
+ "NameSeasonNumber": "Sería {0}",
+ "MixedContent": "Blandað efni",
+ "MessageServerConfigurationUpdated": "Stillingar miðlarans hefur verið uppfærð",
+ "MessageApplicationUpdatedTo": "Jellyfin Server hefur verið uppfærður í {0}",
+ "MessageApplicationUpdated": "Jellyfin Server hefur verið uppfærður",
+ "Latest": "Nýjasta",
+ "LabelRunningTimeValue": "Keyrslutími kerfis: {0}",
+ "User": "Notandi",
+ "System": "Kerfi",
+ "NotificationOptionNewLibraryContent": "Nýju efni bætt við",
+ "NewVersionIsAvailable": "Ný útgáfa af Jellyfin Server er fáanleg til niðurhals.",
+ "NameInstallFailed": "{0} uppsetning mistókst",
+ "MusicVideos": "Tónlistarmyndbönd",
+ "Music": "Tónlist",
+ "Movies": "Kvikmyndir",
+ "UserDeletedWithName": "Notanda {0} hefur verið eytt",
+ "UserCreatedWithName": "Notandi {0} hefur verið stofnaður",
+ "TvShows": "Þættir",
+ "Sync": "Samstilla",
+ "Songs": "Lög",
+ "ServerNameNeedsToBeRestarted": "{0} þarf að endurræsa",
+ "ScheduledTaskStartedWithName": "{0} hafin",
+ "ScheduledTaskFailedWithName": "{0} mistókst",
+ "PluginUpdatedWithName": "{0} var uppfært",
+ "PluginUninstalledWithName": "{0} var fjarlægt",
+ "PluginInstalledWithName": "{0} var sett upp",
+ "NotificationOptionTaskFailed": "Tímasett verkefni mistókst"
+}
diff --git a/Emby.Server.Implementations/Localization/Core/it.json b/Emby.Server.Implementations/Localization/Core/it.json
index 357883cd3..8f91effb9 100644
--- a/Emby.Server.Implementations/Localization/Core/it.json
+++ b/Emby.Server.Implementations/Localization/Core/it.json
@@ -9,13 +9,13 @@
"Channels": "Canali",
"ChapterNameValue": "Capitolo {0}",
"Collections": "Collezioni",
- "DeviceOfflineWithName": "{0} è stato disconnesso",
+ "DeviceOfflineWithName": "{0} ha disconnesso",
"DeviceOnlineWithName": "{0} è connesso",
"FailedLoginAttemptWithUserName": "Tentativo di accesso fallito da {0}",
"Favorites": "Preferiti",
"Folders": "Cartelle",
"Genres": "Generi",
- "HeaderAlbumArtists": "Artisti Album",
+ "HeaderAlbumArtists": "Artisti dell' Album",
"HeaderCameraUploads": "Caricamenti Fotocamera",
"HeaderContinueWatching": "Continua a guardare",
"HeaderFavoriteAlbums": "Album preferiti",
@@ -32,7 +32,7 @@
"ItemRemovedWithName": "{0} è stato rimosso dalla libreria",
"LabelIpAddressValue": "Indirizzo IP: {0}",
"LabelRunningTimeValue": "Durata: {0}",
- "Latest": "Più recenti",
+ "Latest": "Novità",
"MessageApplicationUpdated": "Il Server Jellyfin è stato aggiornato",
"MessageApplicationUpdatedTo": "Jellyfin Server è stato aggiornato a {0}",
"MessageNamedServerConfigurationUpdatedWithValue": "La sezione {0} della configurazione server è stata aggiornata",
@@ -43,7 +43,7 @@
"MusicVideos": "Video musicali",
"NameInstallFailed": "{0} installazione fallita",
"NameSeasonNumber": "Stagione {0}",
- "NameSeasonUnknown": "Stagione sconosciuto",
+ "NameSeasonUnknown": "Stagione sconosciuta",
"NewVersionIsAvailable": "Una nuova versione di Jellyfin Server è disponibile per il download.",
"NotificationOptionApplicationUpdateAvailable": "Aggiornamento dell'applicazione disponibile",
"NotificationOptionApplicationUpdateInstalled": "Aggiornamento dell'applicazione installato",
@@ -88,9 +88,9 @@
"UserOfflineFromDevice": "{0} è stato disconnesso da {1}",
"UserOnlineFromDevice": "{0} è online da {1}",
"UserPasswordChangedWithName": "La password è stata cambiata per l'utente {0}",
- "UserPolicyUpdatedWithName": "La politica dell'utente è stata aggiornata per {0}",
- "UserStartedPlayingItemWithValues": "{0} ha avviato la riproduzione di {1}",
- "UserStoppedPlayingItemWithValues": "{0} ha interrotto la riproduzione di {1}",
+ "UserPolicyUpdatedWithName": "La policy dell'utente è stata aggiornata per {0}",
+ "UserStartedPlayingItemWithValues": "{0} ha avviato la riproduzione di {1} su {2}",
+ "UserStoppedPlayingItemWithValues": "{0} ha interrotto la riproduzione di {1} su {2}",
"ValueHasBeenAddedToLibrary": "{0} è stato aggiunto alla tua libreria multimediale",
"ValueSpecialEpisodeName": "Speciale - {0}",
"VersionNumber": "Versione {0}"
diff --git a/Emby.Server.Implementations/Localization/Core/ko.json b/Emby.Server.Implementations/Localization/Core/ko.json
index 3d2350c07..0320a0a1b 100644
--- a/Emby.Server.Implementations/Localization/Core/ko.json
+++ b/Emby.Server.Implementations/Localization/Core/ko.json
@@ -5,13 +5,13 @@
"Artists": "아티스트",
"AuthenticationSucceededWithUserName": "{0}이 성공적으로 인증됨",
"Books": "도서",
- "CameraImageUploadedFrom": "{0}에서 새로운 카메라 이미지가 업로드되었습니다",
+ "CameraImageUploadedFrom": "{0}에서 새로운 카메라 이미지가 업로드됨",
"Channels": "채널",
"ChapterNameValue": "챕터 {0}",
"Collections": "컬렉션",
- "DeviceOfflineWithName": "{0} 연결 끊김",
- "DeviceOnlineWithName": "{0} 연결됨",
- "FailedLoginAttemptWithUserName": "{0} 로그인 실패",
+ "DeviceOfflineWithName": "{0}의 연결 끊김",
+ "DeviceOnlineWithName": "{0}이 연결됨",
+ "FailedLoginAttemptWithUserName": "{0}에서 로그인 실패",
"Favorites": "즐겨찾기",
"Folders": "폴더",
"Genres": "장르",
diff --git a/Emby.Server.Implementations/Localization/Core/lt-LT.json b/Emby.Server.Implementations/Localization/Core/lt-LT.json
index e2f3ba3dc..e8e1b7740 100644
--- a/Emby.Server.Implementations/Localization/Core/lt-LT.json
+++ b/Emby.Server.Implementations/Localization/Core/lt-LT.json
@@ -1,97 +1,97 @@
{
"Albums": "Albumai",
- "AppDeviceValues": "App: {0}, Device: {1}",
- "Application": "Application",
+ "AppDeviceValues": "Programa: {0}, Įrenginys: {1}",
+ "Application": "Programa",
"Artists": "Atlikėjai",
- "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "AuthenticationSucceededWithUserName": "{0} sėkmingai autentifikuota",
"Books": "Knygos",
- "CameraImageUploadedFrom": "A new camera image has been uploaded from {0}",
+ "CameraImageUploadedFrom": "Nauja nuotrauka įkelta iš kameros {0}",
"Channels": "Kanalai",
- "ChapterNameValue": "Chapter {0}",
+ "ChapterNameValue": "Scena{0}",
"Collections": "Kolekcijos",
- "DeviceOfflineWithName": "{0} has disconnected",
- "DeviceOnlineWithName": "{0} is connected",
- "FailedLoginAttemptWithUserName": "Failed login attempt from {0}",
+ "DeviceOfflineWithName": "{0} buvo atjungtas",
+ "DeviceOnlineWithName": "{0} prisijungęs",
+ "FailedLoginAttemptWithUserName": "{0} - nesėkmingas bandymas prisijungti",
"Favorites": "Mėgstami",
"Folders": "Katalogai",
"Genres": "Žanrai",
"HeaderAlbumArtists": "Albumo atlikėjai",
- "HeaderCameraUploads": "Camera Uploads",
+ "HeaderCameraUploads": "Kameros",
"HeaderContinueWatching": "Žiūrėti toliau",
- "HeaderFavoriteAlbums": "Favorite Albums",
- "HeaderFavoriteArtists": "Favorite Artists",
- "HeaderFavoriteEpisodes": "Favorite Episodes",
- "HeaderFavoriteShows": "Favorite Shows",
- "HeaderFavoriteSongs": "Favorite Songs",
- "HeaderLiveTV": "Live TV",
- "HeaderNextUp": "Next Up",
- "HeaderRecordingGroups": "Recording Groups",
- "HomeVideos": "Home videos",
- "Inherit": "Inherit",
- "ItemAddedWithName": "{0} was added to the library",
- "ItemRemovedWithName": "{0} was removed from the library",
- "LabelIpAddressValue": "Ip address: {0}",
- "LabelRunningTimeValue": "Running time: {0}",
- "Latest": "Latest",
- "MessageApplicationUpdated": "Jellyfin Server has been updated",
- "MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}",
- "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
- "MessageServerConfigurationUpdated": "Server configuration has been updated",
+ "HeaderFavoriteAlbums": "Mėgstami Albumai",
+ "HeaderFavoriteArtists": "Mėgstami Atlikėjai",
+ "HeaderFavoriteEpisodes": "Mėgstamiausios serijos",
+ "HeaderFavoriteShows": "Mėgstamiausi serialai",
+ "HeaderFavoriteSongs": "Mėgstamos dainos",
+ "HeaderLiveTV": "TV gyvai",
+ "HeaderNextUp": "Toliau eilėje",
+ "HeaderRecordingGroups": "Įrašų grupės",
+ "HomeVideos": "Namų vaizdo įrašai",
+ "Inherit": "Paveldėti",
+ "ItemAddedWithName": "{0} - buvo įkeltas į mediateką",
+ "ItemRemovedWithName": "{0} - buvo pašalinta iš mediatekos",
+ "LabelIpAddressValue": "IP adresas: {0}",
+ "LabelRunningTimeValue": "Trukmė: {0}",
+ "Latest": "Naujausi",
+ "MessageApplicationUpdated": "\"Jellyfin Server\" atnaujintas",
+ "MessageApplicationUpdatedTo": "\"Jellyfin Server\" buvo atnaujinta iki {0}",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Serverio nustatymai (skyrius {0}) buvo atnaujinti",
+ "MessageServerConfigurationUpdated": "Serverio nustatymai buvo atnaujinti",
"MixedContent": "Mixed content",
"Movies": "Filmai",
- "Music": "Music",
- "MusicVideos": "Music videos",
- "NameInstallFailed": "{0} installation failed",
- "NameSeasonNumber": "Season {0}",
- "NameSeasonUnknown": "Season Unknown",
- "NewVersionIsAvailable": "A new version of Jellyfin Server is available for download.",
- "NotificationOptionApplicationUpdateAvailable": "Application update available",
- "NotificationOptionApplicationUpdateInstalled": "Application update installed",
- "NotificationOptionAudioPlayback": "Audio playback started",
- "NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
- "NotificationOptionCameraImageUploaded": "Camera image uploaded",
- "NotificationOptionInstallationFailed": "Installation failure",
- "NotificationOptionNewLibraryContent": "New content added",
- "NotificationOptionPluginError": "Plugin failure",
- "NotificationOptionPluginInstalled": "Plugin installed",
- "NotificationOptionPluginUninstalled": "Plugin uninstalled",
- "NotificationOptionPluginUpdateInstalled": "Plugin update installed",
- "NotificationOptionServerRestartRequired": "Server restart required",
- "NotificationOptionTaskFailed": "Scheduled task failure",
- "NotificationOptionUserLockedOut": "User locked out",
- "NotificationOptionVideoPlayback": "Video playback started",
- "NotificationOptionVideoPlaybackStopped": "Video playback stopped",
- "Photos": "Photos",
- "Playlists": "Playlists",
+ "Music": "Muzika",
+ "MusicVideos": "Muzikiniai klipai",
+ "NameInstallFailed": "{0} diegimo klaida",
+ "NameSeasonNumber": "Sezonas {0}",
+ "NameSeasonUnknown": "Sezonas neatpažintas",
+ "NewVersionIsAvailable": "Nauja \"Jellyfin Server\" versija yra prieinama atsisiuntimui.",
+ "NotificationOptionApplicationUpdateAvailable": "Galimi programos atnaujinimai",
+ "NotificationOptionApplicationUpdateInstalled": "Programos atnaujinimai įdiegti",
+ "NotificationOptionAudioPlayback": "Garso atkūrimas pradėtas",
+ "NotificationOptionAudioPlaybackStopped": "Garso atkūrimas sustabdytas",
+ "NotificationOptionCameraImageUploaded": "Kameros vaizdai įkelti",
+ "NotificationOptionInstallationFailed": "Diegimo klaida",
+ "NotificationOptionNewLibraryContent": "Naujas turinys įkeltas",
+ "NotificationOptionPluginError": "Įskiepio klaida",
+ "NotificationOptionPluginInstalled": "Įskiepis įdiegtas",
+ "NotificationOptionPluginUninstalled": "Įskiepis pašalintas",
+ "NotificationOptionPluginUpdateInstalled": "Įskiepio atnaujinimas įdiegtas",
+ "NotificationOptionServerRestartRequired": "Reikalingas serverio perleidimas",
+ "NotificationOptionTaskFailed": "Suplanuotos užduoties klaida",
+ "NotificationOptionUserLockedOut": "Vartotojas užblokuotas",
+ "NotificationOptionVideoPlayback": "Vaizdo įrašo atkūrimas pradėtas",
+ "NotificationOptionVideoPlaybackStopped": "Vaizdo įrašo atkūrimas sustabdytas",
+ "Photos": "Nuotraukos",
+ "Playlists": "Grojaraštis",
"Plugin": "Plugin",
- "PluginInstalledWithName": "{0} was installed",
- "PluginUninstalledWithName": "{0} was uninstalled",
- "PluginUpdatedWithName": "{0} was updated",
+ "PluginInstalledWithName": "{0} buvo įdiegtas",
+ "PluginUninstalledWithName": "{0} buvo pašalintas",
+ "PluginUpdatedWithName": "{0} buvo atnaujintas",
"ProviderValue": "Provider: {0}",
- "ScheduledTaskFailedWithName": "{0} failed",
- "ScheduledTaskStartedWithName": "{0} started",
- "ServerNameNeedsToBeRestarted": "{0} needs to be restarted",
- "Shows": "Shows",
- "Songs": "Songs",
- "StartupEmbyServerIsLoading": "Jellyfin Server is loading. Please try again shortly.",
+ "ScheduledTaskFailedWithName": "{0} klaida",
+ "ScheduledTaskStartedWithName": "{0} paleista",
+ "ServerNameNeedsToBeRestarted": "{0} reikia iš naujo paleisti",
+ "Shows": "Laidos",
+ "Songs": "Kūriniai",
+ "StartupEmbyServerIsLoading": "Jellyfin Server kraunasi. Netrukus pabandykite dar kartą.",
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
- "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}",
- "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
+ "SubtitleDownloadFailureFromForItem": "{1} subtitrai buvo nesėkmingai parsiųsti iš {0}",
+ "SubtitlesDownloadedForItem": "{0} subtitrai parsiųsti",
"Sync": "Sinchronizuoti",
"System": "System",
- "TvShows": "TV Shows",
+ "TvShows": "TV Serialai",
"User": "User",
- "UserCreatedWithName": "User {0} has been created",
- "UserDeletedWithName": "User {0} has been deleted",
- "UserDownloadingItemWithValues": "{0} is downloading {1}",
- "UserLockedOutWithName": "User {0} has been locked out",
- "UserOfflineFromDevice": "{0} has disconnected from {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} is playing {1} on {2}",
- "UserStoppedPlayingItemWithValues": "{0} has finished playing {1} on {2}",
- "ValueHasBeenAddedToLibrary": "{0} has been added to your media library",
+ "UserCreatedWithName": "Vartotojas {0} buvo sukurtas",
+ "UserDeletedWithName": "Vartotojas {0} ištrintas",
+ "UserDownloadingItemWithValues": "{0} siunčiasi {1}",
+ "UserLockedOutWithName": "Vartotojas {0} užblokuotas",
+ "UserOfflineFromDevice": "{0} buvo atjungtas nuo {1}",
+ "UserOnlineFromDevice": "{0} prisijungęs iš {1}",
+ "UserPasswordChangedWithName": "Slaptažodis pakeistas vartotojui {0}",
+ "UserPolicyUpdatedWithName": "Vartotojo {0} teisės buvo pakeistos",
+ "UserStartedPlayingItemWithValues": "{0} leidžia {1} į {2}",
+ "UserStoppedPlayingItemWithValues": "{0} baigė leisti {1} į {2}",
+ "ValueHasBeenAddedToLibrary": "{0} pridėtas į mediateką",
"ValueSpecialEpisodeName": "Ypatinga - {0}",
"VersionNumber": "Version {0}"
}
diff --git a/Emby.Server.Implementations/Localization/Core/nb.json b/Emby.Server.Implementations/Localization/Core/nb.json
index 1237fb70a..7d4b2bdac 100644
--- a/Emby.Server.Implementations/Localization/Core/nb.json
+++ b/Emby.Server.Implementations/Localization/Core/nb.json
@@ -17,7 +17,7 @@
"Genres": "Sjangre",
"HeaderAlbumArtists": "Albumartister",
"HeaderCameraUploads": "Kameraopplastinger",
- "HeaderContinueWatching": "Forsett å se på",
+ "HeaderContinueWatching": "Fortsett å se",
"HeaderFavoriteAlbums": "Favorittalbum",
"HeaderFavoriteArtists": "Favorittartister",
"HeaderFavoriteEpisodes": "Favorittepisoder",
@@ -25,18 +25,18 @@
"HeaderFavoriteSongs": "Favorittsanger",
"HeaderLiveTV": "Direkte-TV",
"HeaderNextUp": "Neste",
- "HeaderRecordingGroups": "Opptak Grupper",
- "HomeVideos": "Hjemmelaget filmer",
+ "HeaderRecordingGroups": "Opptaksgrupper",
+ "HomeVideos": "Hjemmelagde filmer",
"Inherit": "Arve",
"ItemAddedWithName": "{0} ble lagt til i biblioteket",
"ItemRemovedWithName": "{0} ble fjernet fra biblioteket",
- "LabelIpAddressValue": "IP adresse: {0}",
- "LabelRunningTimeValue": "Løpetid {0}",
+ "LabelIpAddressValue": "IP-adresse: {0}",
+ "LabelRunningTimeValue": "Kjøretid {0}",
"Latest": "Siste",
- "MessageApplicationUpdated": "Jellyfin server har blitt oppdatert",
- "MessageApplicationUpdatedTo": "Jellyfin-serveren ble oppdatert til {0}",
- "MessageNamedServerConfigurationUpdatedWithValue": "Server konfigurasjon seksjon {0} har blitt oppdatert",
- "MessageServerConfigurationUpdated": "Server konfigurasjon er oppdatert",
+ "MessageApplicationUpdated": "Jellyfin Server har blitt oppdatert",
+ "MessageApplicationUpdatedTo": "Jellyfin Server ble oppdatert til {0}",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Serverkonfigurasjon seksjon {0} har blitt oppdatert",
+ "MessageServerConfigurationUpdated": "Serverkonfigurasjon er oppdatert",
"MixedContent": "Blandet innhold",
"Movies": "Filmer",
"Music": "Musikk",
@@ -44,38 +44,38 @@
"NameInstallFailed": "{0}-installasjonen mislyktes",
"NameSeasonNumber": "Sesong {0}",
"NameSeasonUnknown": "Sesong ukjent",
- "NewVersionIsAvailable": "En ny versjon av Jellyfin-serveren er tilgjengelig for nedlastning.",
- "NotificationOptionApplicationUpdateAvailable": "Applikasjon oppdatering tilgjengelig",
+ "NewVersionIsAvailable": "En ny versjon av Jellyfin Server er tilgjengelig for nedlasting.",
+ "NotificationOptionApplicationUpdateAvailable": "Programvareoppdatering er tilgjengelig",
"NotificationOptionApplicationUpdateInstalled": "Applikasjonsoppdatering installert",
- "NotificationOptionAudioPlayback": "Lyd tilbakespilling startet",
- "NotificationOptionAudioPlaybackStopped": "Lyd avspilling stoppet",
- "NotificationOptionCameraImageUploaded": "Kamera bilde lastet opp",
+ "NotificationOptionAudioPlayback": "Lydavspilling startet",
+ "NotificationOptionAudioPlaybackStopped": "Lydavspilling stoppet",
+ "NotificationOptionCameraImageUploaded": "Kamerabilde lastet opp",
"NotificationOptionInstallationFailed": "Installasjonsfeil",
- "NotificationOptionNewLibraryContent": "Ny innhold er lagt til",
- "NotificationOptionPluginError": "Plugin feil",
+ "NotificationOptionNewLibraryContent": "Nytt innhold lagt til",
+ "NotificationOptionPluginError": "Pluginfeil",
"NotificationOptionPluginInstalled": "Plugin installert",
"NotificationOptionPluginUninstalled": "Plugin avinstallert",
- "NotificationOptionPluginUpdateInstalled": "Plugin oppdatering installert",
- "NotificationOptionServerRestartRequired": "Server omstart er nødvendig",
- "NotificationOptionTaskFailed": "Feil under utføring av planlagt oppgaver",
+ "NotificationOptionPluginUpdateInstalled": "Pluginoppdatering installert",
+ "NotificationOptionServerRestartRequired": "Serveromstart er nødvendig",
+ "NotificationOptionTaskFailed": "Feil under utføring av planlagt oppgave",
"NotificationOptionUserLockedOut": "Bruker er utestengt",
- "NotificationOptionVideoPlayback": "Video tilbakespilling startet",
- "NotificationOptionVideoPlaybackStopped": "Video avspilling stoppet",
+ "NotificationOptionVideoPlayback": "Videoavspilling startet",
+ "NotificationOptionVideoPlaybackStopped": "Videoavspilling stoppet",
"Photos": "Bilder",
- "Playlists": "Spillelister",
+ "Playlists": "Spliielister",
"Plugin": "Plugin",
"PluginInstalledWithName": "{0} ble installert",
"PluginUninstalledWithName": "{0} ble avinstallert",
"PluginUpdatedWithName": "{0} ble oppdatert",
- "ProviderValue": "Leverandører: {0}",
- "ScheduledTaskFailedWithName": "{0} Mislykkes",
- "ScheduledTaskStartedWithName": "{0} Startet",
+ "ProviderValue": "Leverandør: {0}",
+ "ScheduledTaskFailedWithName": "{0} mislykkes",
+ "ScheduledTaskStartedWithName": "{0} startet",
"ServerNameNeedsToBeRestarted": "{0} må startes på nytt",
"Shows": "Programmer",
"Songs": "Sanger",
- "StartupEmbyServerIsLoading": "Jellyfin server laster. Prøv igjen snart.",
+ "StartupEmbyServerIsLoading": "Jellyfin Server laster. Prøv igjen snart.",
"SubtitleDownloadFailureForItem": "En feil oppstå under nedlasting av undertekster for {0}",
- "SubtitleDownloadFailureFromForItem": "Kunne ikke laste ned teksting fra {0} for {1}",
+ "SubtitleDownloadFailureFromForItem": "Kunne ikke laste ned undertekster fra {0} for {1}",
"SubtitlesDownloadedForItem": "Undertekster lastet ned for {0}",
"Sync": "Synkroniser",
"System": "System",
diff --git a/Emby.Server.Implementations/Localization/Core/nl.json b/Emby.Server.Implementations/Localization/Core/nl.json
index 637e514ed..4423b7f98 100644
--- a/Emby.Server.Implementations/Localization/Core/nl.json
+++ b/Emby.Server.Implementations/Localization/Core/nl.json
@@ -5,10 +5,10 @@
"Artists": "Artiesten",
"AuthenticationSucceededWithUserName": "{0} is succesvol geverifieerd",
"Books": "Boeken",
- "CameraImageUploadedFrom": "Er is een nieuwe foto toegevoegd via {0}",
+ "CameraImageUploadedFrom": "Er is een nieuwe foto toegevoegd van {0}",
"Channels": "Kanalen",
"ChapterNameValue": "Hoofdstuk {0}",
- "Collections": "Collecties",
+ "Collections": "Verzamelingen",
"DeviceOfflineWithName": "{0} heeft de verbinding verbroken",
"DeviceOnlineWithName": "{0} is verbonden",
"FailedLoginAttemptWithUserName": "Mislukte aanmeld poging van {0}",
@@ -58,7 +58,7 @@
"NotificationOptionPluginUpdateInstalled": "Plug-in-update geïnstalleerd",
"NotificationOptionServerRestartRequired": "Server herstart nodig",
"NotificationOptionTaskFailed": "Geplande taak mislukt",
- "NotificationOptionUserLockedOut": "Gebruikersaccount vergrendeld",
+ "NotificationOptionUserLockedOut": "Gebruiker is vergrendeld",
"NotificationOptionVideoPlayback": "Video gestart",
"NotificationOptionVideoPlaybackStopped": "Video gestopt",
"Photos": "Foto's",
diff --git a/Emby.Server.Implementations/Localization/Core/pt-BR.json b/Emby.Server.Implementations/Localization/Core/pt-BR.json
index faa8499b8..41a389e3b 100644
--- a/Emby.Server.Implementations/Localization/Core/pt-BR.json
+++ b/Emby.Server.Implementations/Localization/Core/pt-BR.json
@@ -1,7 +1,7 @@
{
"Albums": "Álbuns",
"AppDeviceValues": "App: {0}, Dispositivo: {1}",
- "Application": "Inscrição",
+ "Application": "Aplicativo",
"Artists": "Artistas",
"AuthenticationSucceededWithUserName": "{0} autenticado com sucesso",
"Books": "Livros",
@@ -10,7 +10,7 @@
"ChapterNameValue": "Capítulo {0}",
"Collections": "Coletâneas",
"DeviceOfflineWithName": "{0} se desconectou",
- "DeviceOnlineWithName": "{0} está conectado",
+ "DeviceOnlineWithName": "{0} se conectou",
"FailedLoginAttemptWithUserName": "Falha na tentativa de login de {0}",
"Favorites": "Favoritos",
"Folders": "Pastas",
@@ -24,7 +24,7 @@
"HeaderFavoriteShows": "Séries Favoritas",
"HeaderFavoriteSongs": "Músicas Favoritas",
"HeaderLiveTV": "TV ao Vivo",
- "HeaderNextUp": "Próximos",
+ "HeaderNextUp": "A Seguir",
"HeaderRecordingGroups": "Grupos de Gravação",
"HomeVideos": "Vídeos caseiros",
"Inherit": "Herdar",
@@ -40,16 +40,16 @@
"MixedContent": "Conteúdo misto",
"Movies": "Filmes",
"Music": "Música",
- "MusicVideos": "Clipes",
+ "MusicVideos": "Videoclipes",
"NameInstallFailed": "A instalação de {0} falhou",
"NameSeasonNumber": "Temporada {0}",
"NameSeasonUnknown": "Temporada Desconhecida",
"NewVersionIsAvailable": "Uma nova versão do Servidor Jellyfin está disponível para download.",
- "NotificationOptionApplicationUpdateAvailable": "Atualização de aplicativo disponível",
- "NotificationOptionApplicationUpdateInstalled": "Atualização de aplicativo instalada",
+ "NotificationOptionApplicationUpdateAvailable": "Atualização do aplicativo disponível",
+ "NotificationOptionApplicationUpdateInstalled": "Atualização do aplicativo instalada",
"NotificationOptionAudioPlayback": "Reprodução de áudio iniciada",
"NotificationOptionAudioPlaybackStopped": "Reprodução de áudio parada",
- "NotificationOptionCameraImageUploaded": "Imagem de câmera enviada",
+ "NotificationOptionCameraImageUploaded": "Imagem da câmera enviada",
"NotificationOptionInstallationFailed": "Falha na instalação",
"NotificationOptionNewLibraryContent": "Novo conteúdo adicionado",
"NotificationOptionPluginError": "Falha de plugin",
@@ -73,7 +73,7 @@
"ServerNameNeedsToBeRestarted": "O servidor {0} precisa ser reiniciado",
"Shows": "Séries",
"Songs": "Músicas",
- "StartupEmbyServerIsLoading": "O Servidor Jellyfin está carregando. Por favor tente novamente em breve.",
+ "StartupEmbyServerIsLoading": "O Servidor Jellyfin está carregando. Por favor, tente novamente mais tarde.",
"SubtitleDownloadFailureForItem": "Download de legendas falhou para {0}",
"SubtitleDownloadFailureFromForItem": "Houve um problema ao baixar as legendas de {0} para {1}",
"SubtitlesDownloadedForItem": "Legendas baixadas para {0}",
@@ -86,12 +86,12 @@
"UserDownloadingItemWithValues": "{0} está baixando {1}",
"UserLockedOutWithName": "Usuário {0} foi bloqueado",
"UserOfflineFromDevice": "{0} se desconectou de {1}",
- "UserOnlineFromDevice": "{0} está ativo em {1}",
+ "UserOnlineFromDevice": "{0} está online em {1}",
"UserPasswordChangedWithName": "A senha foi alterada para o usuário {0}",
"UserPolicyUpdatedWithName": "A política de usuário foi atualizada para {0}",
- "UserStartedPlayingItemWithValues": "{0} iniciou a reprodução de {1}",
- "UserStoppedPlayingItemWithValues": "{0} parou de reproduzir {1}",
- "ValueHasBeenAddedToLibrary": "{0} foi adicionado a sua biblioteca",
+ "UserStartedPlayingItemWithValues": "{0} está reproduzindo {1} em {2}",
+ "UserStoppedPlayingItemWithValues": "{0} parou de reproduzir {1} em {2}",
+ "ValueHasBeenAddedToLibrary": "{0} foi adicionado à sua biblioteca de mídia",
"ValueSpecialEpisodeName": "Especial - {0}",
"VersionNumber": "Versão {0}"
}
diff --git a/Emby.Server.Implementations/Localization/Core/pt.json b/Emby.Server.Implementations/Localization/Core/pt.json
new file mode 100644
index 000000000..ef8d988c8
--- /dev/null
+++ b/Emby.Server.Implementations/Localization/Core/pt.json
@@ -0,0 +1,96 @@
+{
+ "HeaderLiveTV": "TV ao Vivo",
+ "Collections": "Colecções",
+ "Books": "Livros",
+ "Artists": "Artistas",
+ "Albums": "Álbuns",
+ "HeaderNextUp": "A Seguir",
+ "HeaderFavoriteSongs": "Músicas Favoritas",
+ "HeaderFavoriteArtists": "Artistas Favoritos",
+ "HeaderFavoriteAlbums": "Álbuns Favoritos",
+ "HeaderFavoriteEpisodes": "Episódios Favoritos",
+ "HeaderFavoriteShows": "Séries Favoritas",
+ "HeaderContinueWatching": "Continuar a Ver",
+ "HeaderAlbumArtists": "Artistas do Álbum",
+ "Genres": "Géneros",
+ "Folders": "Pastas",
+ "Favorites": "Favoritos",
+ "Channels": "Canais",
+ "UserDownloadingItemWithValues": "{0} está a transferir {1}",
+ "VersionNumber": "Versão {0}",
+ "ValueHasBeenAddedToLibrary": "{0} foi adicionado à sua biblioteca multimédia",
+ "UserStoppedPlayingItemWithValues": "{0} terminou a reprodução de {1} em {2}",
+ "UserStartedPlayingItemWithValues": "{0} está a reproduzir {1} em {2}",
+ "UserPolicyUpdatedWithName": "A política do utilizador {0} foi alterada",
+ "UserPasswordChangedWithName": "A palavra-passe do utilizador {0} foi alterada",
+ "UserOnlineFromDevice": "{0} ligou-se a partir de {1}",
+ "UserOfflineFromDevice": "{0} desligou-se a partir de {1}",
+ "UserLockedOutWithName": "Utilizador {0} bloqueado",
+ "UserDeletedWithName": "Utilizador {0} removido",
+ "UserCreatedWithName": "Utilizador {0} criado",
+ "User": "Utilizador",
+ "TvShows": "Programas",
+ "System": "Sistema",
+ "SubtitlesDownloadedForItem": "Legendas transferidas para {0}",
+ "SubtitleDownloadFailureFromForItem": "Falha na transferência de legendas de {0} para {1}",
+ "StartupEmbyServerIsLoading": "O servidor Jellyfin está a iniciar. Tente novamente dentro de momentos.",
+ "ServerNameNeedsToBeRestarted": "{0} necessita ser reiniciado",
+ "ScheduledTaskStartedWithName": "{0} iniciou",
+ "ScheduledTaskFailedWithName": "{0} falhou",
+ "ProviderValue": "Fornecedor: {0}",
+ "PluginUpdatedWithName": "{0} foi actualizado",
+ "PluginUninstalledWithName": "{0} foi desinstalado",
+ "PluginInstalledWithName": "{0} foi instalado",
+ "Plugin": "Extensão",
+ "NotificationOptionVideoPlaybackStopped": "Reprodução de vídeo parada",
+ "NotificationOptionVideoPlayback": "Reprodução de vídeo iniciada",
+ "NotificationOptionUserLockedOut": "Utilizador bloqueado",
+ "NotificationOptionTaskFailed": "Falha em tarefa agendada",
+ "NotificationOptionServerRestartRequired": "É necessário reiniciar o servidor",
+ "NotificationOptionPluginUpdateInstalled": "Extensão actualizada",
+ "NotificationOptionPluginUninstalled": "Extensão desinstalada",
+ "NotificationOptionPluginInstalled": "Extensão instalada",
+ "NotificationOptionPluginError": "Falha na extensão",
+ "NotificationOptionNewLibraryContent": "Novo conteúdo adicionado",
+ "NotificationOptionInstallationFailed": "Falha de instalação",
+ "NotificationOptionCameraImageUploaded": "Imagem da câmara enviada",
+ "NotificationOptionAudioPlaybackStopped": "Reprodução Parada",
+ "NotificationOptionAudioPlayback": "Reprodução Iniciada",
+ "NotificationOptionApplicationUpdateInstalled": "A actualização da aplicação foi instalada",
+ "NotificationOptionApplicationUpdateAvailable": "Uma actualização da aplicação está disponível",
+ "NewVersionIsAvailable": "Uma nova versão do servidor Jellyfin está disponível para transferência.",
+ "NameSeasonUnknown": "Temporada Desconhecida",
+ "NameSeasonNumber": "Temporada {0}",
+ "NameInstallFailed": "Falha na instalação de {0}",
+ "MusicVideos": "Videoclips",
+ "Music": "Música",
+ "MixedContent": "Conteúdo Misto",
+ "MessageServerConfigurationUpdated": "A configuração do servidor foi actualizada",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Configurações do servidor na secção {0} foram atualizadas",
+ "MessageApplicationUpdatedTo": "O servidor Jellyfin foi actualizado para a versão {0}",
+ "MessageApplicationUpdated": "O servidor Jellyfin foi actualizado",
+ "Latest": "Mais Recente",
+ "LabelRunningTimeValue": "Duração: {0}",
+ "LabelIpAddressValue": "Endereço IP: {0}",
+ "ItemRemovedWithName": "{0} foi removido da biblioteca",
+ "ItemAddedWithName": "{0} foi adicionado à biblioteca",
+ "Inherit": "Herdar",
+ "HomeVideos": "Vídeos Caseiros",
+ "HeaderRecordingGroups": "Grupos de Gravação",
+ "ValueSpecialEpisodeName": "Especial - {0}",
+ "Sync": "Sincronização",
+ "Songs": "Músicas",
+ "Shows": "Séries",
+ "Playlists": "Listas de Reprodução",
+ "Photos": "Fotografias",
+ "Movies": "Filmes",
+ "HeaderCameraUploads": "Envios a partir da câmara",
+ "FailedLoginAttemptWithUserName": "Tentativa de ligação a partir de {0} falhou",
+ "DeviceOnlineWithName": "{0} ligou-se",
+ "DeviceOfflineWithName": "{0} desligou-se",
+ "ChapterNameValue": "Capítulo {0}",
+ "CameraImageUploadedFrom": "Uma nova imagem de câmara foi enviada a partir de {0}",
+ "AuthenticationSucceededWithUserName": "{0} autenticado com sucesso",
+ "Application": "Aplicação",
+ "AppDeviceValues": "Aplicação {0}, Dispositivo: {1}"
+}
diff --git a/Emby.Server.Implementations/Localization/Core/ro.json b/Emby.Server.Implementations/Localization/Core/ro.json
new file mode 100644
index 000000000..b871626f0
--- /dev/null
+++ b/Emby.Server.Implementations/Localization/Core/ro.json
@@ -0,0 +1,96 @@
+{
+ "HeaderNextUp": "Urmează",
+ "VersionNumber": "Versiunea {0}",
+ "ValueSpecialEpisodeName": "Special - {0}",
+ "ValueHasBeenAddedToLibrary": "{0} a fost adăugat la biblioteca multimedia",
+ "UserStoppedPlayingItemWithValues": "{0} a terminat rularea {1} pe {2}",
+ "UserStartedPlayingItemWithValues": "{0} ruleaza {1} pe {2}",
+ "UserPolicyUpdatedWithName": "Politica utilizatorului {0} a fost actualizată",
+ "UserPasswordChangedWithName": "Parola utilizatorului {0} a fost schimbată",
+ "UserOnlineFromDevice": "{0} este conectat de la {1}",
+ "UserOfflineFromDevice": "{0} s-a deconectat de la {1}",
+ "UserLockedOutWithName": "Utilizatorul {0} a fost blocat",
+ "UserDownloadingItemWithValues": "{0} descarcă {1}",
+ "UserDeletedWithName": "Utilizatorul {0} a fost eliminat",
+ "UserCreatedWithName": "Utilizatorul {0} a fost creat",
+ "User": "Utilizator",
+ "TvShows": "Spectacole TV",
+ "System": "Sistem",
+ "Sync": "Sincronizare",
+ "SubtitlesDownloadedForItem": "Subtitrari descarcate pentru {0}",
+ "SubtitleDownloadFailureFromForItem": "Subtitrările nu au putut fi descărcate de la {0} pentru {1}",
+ "StartupEmbyServerIsLoading": "Se încarcă serverul Jellyfin. Încercați din nou în scurt timp.",
+ "Songs": "Melodii",
+ "Shows": "Spectacole",
+ "ServerNameNeedsToBeRestarted": "{0} trebuie repornit",
+ "ScheduledTaskStartedWithName": "{0} pornit/ă",
+ "ScheduledTaskFailedWithName": "{0} eșuat/ă",
+ "ProviderValue": "Furnizor: {0}",
+ "PluginUpdatedWithName": "{0} a fost actualizat/ă",
+ "PluginUninstalledWithName": "{0} a fost dezinstalat",
+ "PluginInstalledWithName": "{0} a fost instalat",
+ "Plugin": "Complement",
+ "Playlists": "Liste redare",
+ "Photos": "Fotografii",
+ "NotificationOptionVideoPlaybackStopped": "Redarea video oprită",
+ "NotificationOptionVideoPlayback": "Începută redarea video",
+ "NotificationOptionUserLockedOut": "Utilizatorul a fost blocat",
+ "NotificationOptionTaskFailed": "Activitate programata eșuată",
+ "NotificationOptionServerRestartRequired": "Este necesară repornirea Serverului",
+ "NotificationOptionPluginUpdateInstalled": "Actualizare plugin instalată",
+ "NotificationOptionPluginUninstalled": "Plugin dezinstalat",
+ "NotificationOptionPluginInstalled": "Plugin instalat",
+ "NotificationOptionPluginError": "Plugin-ul a eșuat",
+ "NotificationOptionNewLibraryContent": "Adăugat conținut nou",
+ "NotificationOptionInstallationFailed": "Eșec la instalare",
+ "NotificationOptionCameraImageUploaded": "Încarcată imagine cameră",
+ "NotificationOptionAudioPlaybackStopped": "Redare audio oprită",
+ "NotificationOptionAudioPlayback": "A inceput redarea audio",
+ "NotificationOptionApplicationUpdateInstalled": "Actualizarea aplicației a fost instalată",
+ "NotificationOptionApplicationUpdateAvailable": "Disponibilă o actualizare a aplicației",
+ "NewVersionIsAvailable": "O nouă versiune a Jellyfin Server este disponibilă pentru descărcare.",
+ "NameSeasonUnknown": "Sezon Necunoscut",
+ "NameSeasonNumber": "Sezonul {0}",
+ "NameInstallFailed": "{0} instalare eșuată",
+ "MusicVideos": "Videoclipuri muzicale",
+ "Music": "Muzică",
+ "Movies": "Filme",
+ "MixedContent": "Conținut mixt",
+ "MessageServerConfigurationUpdated": "Configurația serverului a fost actualizată",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Secțiunea de configurare a serverului {0} a fost acualizata",
+ "MessageApplicationUpdatedTo": "Jellyfin Server a fost actualizat la {0}",
+ "MessageApplicationUpdated": "Jellyfin Server a fost actualizat",
+ "Latest": "Cele mai recente",
+ "LabelRunningTimeValue": "Durată: {0}",
+ "LabelIpAddressValue": "Adresa IP: {0}",
+ "ItemRemovedWithName": "{0} a fost eliminat din bibliotecă",
+ "ItemAddedWithName": "{0} a fost adăugat în bibliotecă",
+ "Inherit": "moștenit",
+ "HomeVideos": "Videoclipuri personale",
+ "HeaderRecordingGroups": "Grupuri de înregistrare",
+ "HeaderLiveTV": "TV în Direct",
+ "HeaderFavoriteSongs": "Melodii Favorite",
+ "HeaderFavoriteShows": "Spectacole Favorite",
+ "HeaderFavoriteEpisodes": "Episoade Favorite",
+ "HeaderFavoriteArtists": "Artiști Favoriți",
+ "HeaderFavoriteAlbums": "Albume Favorite",
+ "HeaderContinueWatching": "Vizionează în continuare",
+ "HeaderCameraUploads": "Incărcări Cameră Foto",
+ "HeaderAlbumArtists": "Album Artiști",
+ "Genres": "Genuri",
+ "Folders": "Dosare",
+ "Favorites": "Favorite",
+ "FailedLoginAttemptWithUserName": "Încercare de conectare nereușită de la {0}",
+ "DeviceOnlineWithName": "{0} este conectat",
+ "DeviceOfflineWithName": "{0} s-a deconectat",
+ "Collections": "Colecții",
+ "ChapterNameValue": "Capitol {0}",
+ "Channels": "Canale",
+ "CameraImageUploadedFrom": "O nouă fotografie a fost încărcată din {0}",
+ "Books": "Cărți",
+ "AuthenticationSucceededWithUserName": "{0} autentificare reușită",
+ "Artists": "Artiști",
+ "Application": "Aplicație",
+ "AppDeviceValues": "Aplicație: {0}, Dispozitiv: {1}",
+ "Albums": "Albume"
+}
diff --git a/Emby.Server.Implementations/Localization/Core/ru.json b/Emby.Server.Implementations/Localization/Core/ru.json
index 0ad4b37aa..7cf957a94 100644
--- a/Emby.Server.Implementations/Localization/Core/ru.json
+++ b/Emby.Server.Implementations/Localization/Core/ru.json
@@ -1,11 +1,11 @@
{
"Albums": "Альбомы",
- "AppDeviceValues": "Прил.: {0}, Устр.: {1}",
+ "AppDeviceValues": "Приложение.: {0}, Устройство.: {1}",
"Application": "Приложение",
"Artists": "Исполнители",
"AuthenticationSucceededWithUserName": "{0} - авторизация успешна",
- "Books": "Литература",
- "CameraImageUploadedFrom": "Новое фото было выложено с камеры {0}",
+ "Books": "Книги",
+ "CameraImageUploadedFrom": "Новое фото загружено с камеры {0}",
"Channels": "Каналы",
"ChapterNameValue": "Сцена {0}",
"Collections": "Коллекции",
diff --git a/Emby.Server.Implementations/Localization/Core/sk.json b/Emby.Server.Implementations/Localization/Core/sk.json
index 6eade7942..9bac305a2 100644
--- a/Emby.Server.Implementations/Localization/Core/sk.json
+++ b/Emby.Server.Implementations/Localization/Core/sk.json
@@ -1,28 +1,28 @@
{
"Albums": "Albumy",
- "AppDeviceValues": "Apka: {0}, Zariadenie: {1}",
+ "AppDeviceValues": "Aplikácia: {0}, Zariadenie: {1}",
"Application": "Aplikácia",
"Artists": "Umelci",
"AuthenticationSucceededWithUserName": "{0} úspešne overený",
"Books": "Knihy",
- "CameraImageUploadedFrom": "A new camera image has been uploaded from {0}",
+ "CameraImageUploadedFrom": "Z {0} bola nahraná nová fotografia",
"Channels": "Kanály",
"ChapterNameValue": "Kapitola {0}",
- "Collections": "Zbierky",
+ "Collections": "Kolekcie",
"DeviceOfflineWithName": "{0} sa odpojil",
"DeviceOnlineWithName": "{0} je pripojený",
"FailedLoginAttemptWithUserName": "Neúspešný pokus o prihlásenie z {0}",
"Favorites": "Obľúbené",
"Folders": "Priečinky",
"Genres": "Žánre",
- "HeaderAlbumArtists": "Album Artists",
+ "HeaderAlbumArtists": "Albumy umelcov",
"HeaderCameraUploads": "Nahrané fotografie",
- "HeaderContinueWatching": "Pokračujte v pozeraní",
+ "HeaderContinueWatching": "Pokračovať v pozeraní",
"HeaderFavoriteAlbums": "Obľúbené albumy",
"HeaderFavoriteArtists": "Obľúbení umelci",
"HeaderFavoriteEpisodes": "Obľúbené epizódy",
"HeaderFavoriteShows": "Obľúbené seriály",
- "HeaderFavoriteSongs": "Obľúbené pesničky",
+ "HeaderFavoriteSongs": "Obľúbené piesne",
"HeaderLiveTV": "Živá TV",
"HeaderNextUp": "Nasleduje",
"HeaderRecordingGroups": "Skupiny nahrávok",
@@ -34,7 +34,7 @@
"LabelRunningTimeValue": "Dĺžka: {0}",
"Latest": "Najnovšie",
"MessageApplicationUpdated": "Jellyfin Server bol aktualizovaný",
- "MessageApplicationUpdatedTo": "Jellyfin Server bol aktualizový na {0}",
+ "MessageApplicationUpdatedTo": "Jellyfin Server bol aktualizový na verziu {0}",
"MessageNamedServerConfigurationUpdatedWithValue": "Sekcia {0} konfigurácie servera bola aktualizovaná",
"MessageServerConfigurationUpdated": "Konfigurácia servera bola aktualizovaná",
"MixedContent": "Zmiešaný obsah",
@@ -42,23 +42,23 @@
"Music": "Hudba",
"MusicVideos": "Hudobné videá",
"NameInstallFailed": "Inštalácia {0} zlyhala",
- "NameSeasonNumber": "Sezóna {0}",
- "NameSeasonUnknown": "Neznáma sezóna",
- "NewVersionIsAvailable": "Nová verzia Jellyfin Server je dostupná na stiahnutie.",
- "NotificationOptionApplicationUpdateAvailable": "Je dostupná aktualizácia aplikácie",
+ "NameSeasonNumber": "Séria {0}",
+ "NameSeasonUnknown": "Neznáma séria",
+ "NewVersionIsAvailable": "Nová verzia Jellyfin Serveru je dostupná na stiahnutie.",
+ "NotificationOptionApplicationUpdateAvailable": "Aktualizácia aplikácie je dostupná",
"NotificationOptionApplicationUpdateInstalled": "Aktualizácia aplikácie nainštalovaná",
- "NotificationOptionAudioPlayback": "Spustené prehrávanie audia",
- "NotificationOptionAudioPlaybackStopped": "Zastavené prehrávanie audia",
- "NotificationOptionCameraImageUploaded": "Nahraný obrázok z fotoaparátu",
+ "NotificationOptionAudioPlayback": "Prehrávanie audia bolo spustené",
+ "NotificationOptionAudioPlaybackStopped": "Prehrávanie audia bolo zastavené",
+ "NotificationOptionCameraImageUploaded": "Obrázok z fotoaparátu bol nahraný",
"NotificationOptionInstallationFailed": "Chyba inštalácie",
- "NotificationOptionNewLibraryContent": "Pridaný nový obsah",
+ "NotificationOptionNewLibraryContent": "Nový obsah bol pridaný",
"NotificationOptionPluginError": "Chyba rozšírenia",
"NotificationOptionPluginInstalled": "Rozšírenie nainštalované",
"NotificationOptionPluginUninstalled": "Rozšírenie odinštalované",
"NotificationOptionPluginUpdateInstalled": "Aktualizácia rozšírenia nainštalovaná",
"NotificationOptionServerRestartRequired": "Vyžaduje sa reštart servera",
"NotificationOptionTaskFailed": "Naplánovaná úloha zlyhala",
- "NotificationOptionUserLockedOut": "User locked out",
+ "NotificationOptionUserLockedOut": "Používateľ je uzamknutý",
"NotificationOptionVideoPlayback": "Spustené prehrávanie videa",
"NotificationOptionVideoPlaybackStopped": "Zastavené prehrávanie videa",
"Photos": "Fotky",
@@ -69,9 +69,9 @@
"PluginUpdatedWithName": "{0} bol aktualizovaný",
"ProviderValue": "Poskytovateľ: {0}",
"ScheduledTaskFailedWithName": "{0} zlyhalo",
- "ScheduledTaskStartedWithName": "{0} started",
+ "ScheduledTaskStartedWithName": "{0} zahájených",
"ServerNameNeedsToBeRestarted": "{0} vyžaduje reštart",
- "Shows": "Series",
+ "Shows": "Seriály",
"Songs": "Skladby",
"StartupEmbyServerIsLoading": "Jellyfin Server sa spúšťa. Skúste to prosím o chvíľu znova.",
"SubtitleDownloadFailureForItem": "Sťahovanie titulkov pre {0} zlyhalo",
@@ -84,11 +84,11 @@
"UserCreatedWithName": "Používateľ {0} bol vytvorený",
"UserDeletedWithName": "Používateľ {0} bol vymazaný",
"UserDownloadingItemWithValues": "{0} sťahuje {1}",
- "UserLockedOutWithName": "User {0} has been locked out",
+ "UserLockedOutWithName": "Používateľ {0} bol vymknutý",
"UserOfflineFromDevice": "{0} sa odpojil od {1}",
"UserOnlineFromDevice": "{0} je online z {1}",
"UserPasswordChangedWithName": "Heslo používateľa {0} zmenené",
- "UserPolicyUpdatedWithName": "User policy has been updated for {0}",
+ "UserPolicyUpdatedWithName": "Používateľské zásady pre {0} boli aktualizované",
"UserStartedPlayingItemWithValues": "{0} spustil prehrávanie {1}",
"UserStoppedPlayingItemWithValues": "{0} zastavil prehrávanie {1}",
"ValueHasBeenAddedToLibrary": "{0} bolo pridané do vašej knižnice médií",
diff --git a/Emby.Server.Implementations/Localization/Core/sv.json b/Emby.Server.Implementations/Localization/Core/sv.json
index fb2761a7d..744b0e2d3 100644
--- a/Emby.Server.Implementations/Localization/Core/sv.json
+++ b/Emby.Server.Implementations/Localization/Core/sv.json
@@ -5,7 +5,7 @@
"Artists": "Artister",
"AuthenticationSucceededWithUserName": "{0} har autentiserats",
"Books": "Böcker",
- "CameraImageUploadedFrom": "A new camera image has been uploaded from {0}",
+ "CameraImageUploadedFrom": "En ny kamerabild har laddats upp från {0}",
"Channels": "Kanaler",
"ChapterNameValue": "Kapitel {0}",
"Collections": "Samlingar",
@@ -16,7 +16,7 @@
"Folders": "Mappar",
"Genres": "Genrer",
"HeaderAlbumArtists": "Albumartister",
- "HeaderCameraUploads": "Camera Uploads",
+ "HeaderCameraUploads": "Kamera Uppladdningar",
"HeaderContinueWatching": "Fortsätt kolla på",
"HeaderFavoriteAlbums": "Favoritalbum",
"HeaderFavoriteArtists": "Favoritartister",
@@ -34,17 +34,17 @@
"LabelRunningTimeValue": "Speltid: {0}",
"Latest": "Senaste",
"MessageApplicationUpdated": "Jellyfin Server har uppdaterats",
- "MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}",
+ "MessageApplicationUpdatedTo": "Jellyfin Server har uppgraderats till {0}",
"MessageNamedServerConfigurationUpdatedWithValue": "Serverinställningarna {0} har uppdaterats",
"MessageServerConfigurationUpdated": "Server konfigurationen har uppdaterats",
"MixedContent": "Blandat innehåll",
"Movies": "Filmer",
"Music": "Musik",
"MusicVideos": "Musikvideos",
- "NameInstallFailed": "{0} installation failed",
+ "NameInstallFailed": "{0} installationen misslyckades",
"NameSeasonNumber": "Säsong {0}",
"NameSeasonUnknown": "Okänd säsong",
- "NewVersionIsAvailable": "A new version of Jellyfin Server is available for download.",
+ "NewVersionIsAvailable": "En ny version av Jellyfin Server är klar för nedladdning.",
"NotificationOptionApplicationUpdateAvailable": "Ny programversion tillgänglig",
"NotificationOptionApplicationUpdateInstalled": "Programuppdatering installerad",
"NotificationOptionAudioPlayback": "Ljuduppspelning har påbörjats",
@@ -70,12 +70,12 @@
"ProviderValue": "Källa: {0}",
"ScheduledTaskFailedWithName": "{0} misslyckades",
"ScheduledTaskStartedWithName": "{0} startad",
- "ServerNameNeedsToBeRestarted": "{0} needs to be restarted",
+ "ServerNameNeedsToBeRestarted": "{0} behöver startas om",
"Shows": "Serier",
"Songs": "Låtar",
"StartupEmbyServerIsLoading": "Jellyfin server arbetar. Pröva igen inom kort.",
"SubtitleDownloadFailureForItem": "Nerladdning av undertexter för {0} misslyckades",
- "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}",
+ "SubtitleDownloadFailureFromForItem": "Undertexter misslyckades att ladda ner {0} för {1}",
"SubtitlesDownloadedForItem": "Undertexter har laddats ner till {0}",
"Sync": "Synk",
"System": "System",
@@ -91,7 +91,7 @@
"UserPolicyUpdatedWithName": "Användarpolicyn har uppdaterats för {0}",
"UserStartedPlayingItemWithValues": "{0} har börjat spela upp {1}",
"UserStoppedPlayingItemWithValues": "{0} har avslutat uppspelningen av {1}",
- "ValueHasBeenAddedToLibrary": "{0} has been added to your media library",
+ "ValueHasBeenAddedToLibrary": "{0} har blivit tillagd till ditt mediabibliotek",
"ValueSpecialEpisodeName": "Specialavsnitt - {0}",
"VersionNumber": "Version {0}"
}
diff --git a/Emby.Server.Implementations/Localization/Core/tr.json b/Emby.Server.Implementations/Localization/Core/tr.json
index 24366b070..eb1c2623f 100644
--- a/Emby.Server.Implementations/Localization/Core/tr.json
+++ b/Emby.Server.Implementations/Localization/Core/tr.json
@@ -25,33 +25,33 @@
"HeaderFavoriteSongs": "Favori Şarkılar",
"HeaderLiveTV": "Canlı TV",
"HeaderNextUp": "Sonraki hafta",
- "HeaderRecordingGroups": "Recording Groups",
- "HomeVideos": "Home videos",
- "Inherit": "Inherit",
- "ItemAddedWithName": "{0} was added to the library",
- "ItemRemovedWithName": "{0} was removed from the library",
- "LabelIpAddressValue": "Ip adresi: {0}",
+ "HeaderRecordingGroups": "Kayıt Grupları",
+ "HomeVideos": "Ev videoları",
+ "Inherit": "Devral",
+ "ItemAddedWithName": "{0} kütüphaneye eklendi",
+ "ItemRemovedWithName": "{0} kütüphaneden silindi",
+ "LabelIpAddressValue": "IP adresi: {0}",
"LabelRunningTimeValue": "Çalışma süresi: {0}",
- "Latest": "Latest",
+ "Latest": "En son",
"MessageApplicationUpdated": "Jellyfin Sunucusu güncellendi",
- "MessageApplicationUpdatedTo": "Jellyfin Server has been updated to {0}",
- "MessageNamedServerConfigurationUpdatedWithValue": "Server configuration section {0} has been updated",
- "MessageServerConfigurationUpdated": "Server configuration has been updated",
- "MixedContent": "Mixed content",
+ "MessageApplicationUpdatedTo": "Jellyfin Sunucusu {0} olarak güncellendi",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Sunucu ayarları kısım {0} güncellendi",
+ "MessageServerConfigurationUpdated": "Sunucu ayarları güncellendi",
+ "MixedContent": "Karışık içerik",
"Movies": "Filmler",
"Music": "Müzik",
"MusicVideos": "Müzik videoları",
- "NameInstallFailed": "{0} kurulum başarısız",
+ "NameInstallFailed": "{0} kurulumu başarısız",
"NameSeasonNumber": "Sezon {0}",
"NameSeasonUnknown": "Bilinmeyen Sezon",
"NewVersionIsAvailable": "Jellyfin Sunucusunun yeni bir versiyonu indirmek için hazır.",
"NotificationOptionApplicationUpdateAvailable": "Uygulama güncellemesi mevcut",
"NotificationOptionApplicationUpdateInstalled": "Uygulama güncellemesi yüklendi",
- "NotificationOptionAudioPlayback": "Audio playback started",
- "NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
- "NotificationOptionCameraImageUploaded": "Camera image uploaded",
+ "NotificationOptionAudioPlayback": "Ses çalma başladı",
+ "NotificationOptionAudioPlaybackStopped": "Ses çalma durduruldu",
+ "NotificationOptionCameraImageUploaded": "Kamera fotoğrafı yüklendi",
"NotificationOptionInstallationFailed": "Yükleme başarısız oldu",
- "NotificationOptionNewLibraryContent": "New content added",
+ "NotificationOptionNewLibraryContent": "Yeni içerik eklendi",
"NotificationOptionPluginError": "Eklenti hatası",
"NotificationOptionPluginInstalled": "Eklenti yüklendi",
"NotificationOptionPluginUninstalled": "Eklenti kaldırıldı",
@@ -59,8 +59,8 @@
"NotificationOptionServerRestartRequired": "Sunucu yeniden başlatma gerekli",
"NotificationOptionTaskFailed": "Zamanlanmış görev hatası",
"NotificationOptionUserLockedOut": "Kullanıcı kitlendi",
- "NotificationOptionVideoPlayback": "Video playback started",
- "NotificationOptionVideoPlaybackStopped": "Video playback stopped",
+ "NotificationOptionVideoPlayback": "Video oynatma başladı",
+ "NotificationOptionVideoPlaybackStopped": "Video oynatma durduruldu",
"Photos": "Fotoğraflar",
"Playlists": "Çalma listeleri",
"Plugin": "Eklenti",
@@ -75,23 +75,23 @@
"Songs": "Şarkılar",
"StartupEmbyServerIsLoading": "Jellyfin Sunucusu yükleniyor. Lütfen kısa süre sonra tekrar deneyin.",
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
- "SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}",
- "SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
+ "SubtitleDownloadFailureFromForItem": "{1} için alt yazılar {0} 'dan indirilemedi",
+ "SubtitlesDownloadedForItem": "{0} için altyazılar indirildi",
"Sync": "Eşitle",
- "System": "System",
- "TvShows": "TV Shows",
+ "System": "Sistem",
+ "TvShows": "Diziler",
"User": "Kullanıcı",
- "UserCreatedWithName": "Kullanıcı {0} yaratıldı",
+ "UserCreatedWithName": "{0} kullanıcısı oluşturuldu",
"UserDeletedWithName": "Kullanıcı {0} silindi",
"UserDownloadingItemWithValues": "{0} indiriliyor {1}",
"UserLockedOutWithName": "Kullanıcı {0} kitlendi",
- "UserOfflineFromDevice": "{0} has disconnected from {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} is playing {1} on {2}",
- "UserStoppedPlayingItemWithValues": "{0} has finished playing {1} on {2}",
- "ValueHasBeenAddedToLibrary": "{0} has been added to your media library",
- "ValueSpecialEpisodeName": "Özel -{0}",
- "VersionNumber": "Version {0}"
+ "UserOfflineFromDevice": "{0}, {1} ile bağlantısı kesildi",
+ "UserOnlineFromDevice": "{0}, {1} çevrimiçi",
+ "UserPasswordChangedWithName": "{0} kullanıcısı için şifre değiştirildi",
+ "UserPolicyUpdatedWithName": "Kullanıcı politikası {0} için güncellendi",
+ "UserStartedPlayingItemWithValues": "{0}, {2} cihazında {1} izliyor",
+ "UserStoppedPlayingItemWithValues": "{0}, {2} cihazında {1} izlemeyi bitirdi",
+ "ValueHasBeenAddedToLibrary": "Medya kitaplığınıza {0} eklendi",
+ "ValueSpecialEpisodeName": "Özel - {0}",
+ "VersionNumber": "Versiyon {0}"
}
diff --git a/Emby.Server.Implementations/Localization/Core/zh-CN.json b/Emby.Server.Implementations/Localization/Core/zh-CN.json
index 87f8553ae..a4d53c57e 100644
--- a/Emby.Server.Implementations/Localization/Core/zh-CN.json
+++ b/Emby.Server.Implementations/Localization/Core/zh-CN.json
@@ -24,7 +24,7 @@
"HeaderFavoriteShows": "最爱的节目",
"HeaderFavoriteSongs": "最爱的歌曲",
"HeaderLiveTV": "电视直播",
- "HeaderNextUp": "接下来",
+ "HeaderNextUp": "下一步",
"HeaderRecordingGroups": "录制组",
"HomeVideos": "家庭视频",
"Inherit": "继承",
@@ -34,7 +34,7 @@
"LabelRunningTimeValue": "运行时间:{0}",
"Latest": "最新",
"MessageApplicationUpdated": "Jellyfin 服务器已更新",
- "MessageApplicationUpdatedTo": "Jellyfin Server 的版本已更新为 {0}",
+ "MessageApplicationUpdatedTo": "Jellyfin Server 版本已更新为 {0}",
"MessageNamedServerConfigurationUpdatedWithValue": "服务器配置 {0} 部分已更新",
"MessageServerConfigurationUpdated": "服务器配置已更新",
"MixedContent": "混合内容",
@@ -42,7 +42,7 @@
"Music": "音乐",
"MusicVideos": "音乐视频",
"NameInstallFailed": "{0} 安装失败",
- "NameSeasonNumber": "季 {0}",
+ "NameSeasonNumber": "第 {0} 季",
"NameSeasonUnknown": "未知季",
"NewVersionIsAvailable": "Jellyfin Server 有新版本可以下载。",
"NotificationOptionApplicationUpdateAvailable": "有可用的应用程序更新",
diff --git a/Emby.Server.Implementations/Localization/Core/zh-HK.json b/Emby.Server.Implementations/Localization/Core/zh-HK.json
index 387fc2b92..33fcb2d37 100644
--- a/Emby.Server.Implementations/Localization/Core/zh-HK.json
+++ b/Emby.Server.Implementations/Localization/Core/zh-HK.json
@@ -2,7 +2,7 @@
"Albums": "Albums",
"AppDeviceValues": "App: {0}, Device: {1}",
"Application": "Application",
- "Artists": "Artists",
+ "Artists": "藝人",
"AuthenticationSucceededWithUserName": "{0} successfully authenticated",
"Books": "Books",
"CameraImageUploadedFrom": "A new camera image has been uploaded from {0}",
diff --git a/Emby.Server.Implementations/Localization/Core/zh-TW.json b/Emby.Server.Implementations/Localization/Core/zh-TW.json
index 293fc28a8..33bdbfb98 100644
--- a/Emby.Server.Implementations/Localization/Core/zh-TW.json
+++ b/Emby.Server.Implementations/Localization/Core/zh-TW.json
@@ -1,6 +1,6 @@
{
"Albums": "專輯",
- "AppDeviceValues": "應用: {0}, 裝置: {1}",
+ "AppDeviceValues": "軟體: {0}, 裝置: {1}",
"Application": "應用程式",
"Artists": "演出者",
"AuthenticationSucceededWithUserName": "{0} 成功授權",
diff --git a/Emby.Server.Implementations/Networking/NetworkManager.cs b/Emby.Server.Implementations/Networking/NetworkManager.cs
index 0b3567986..1d8d3cf39 100644
--- a/Emby.Server.Implementations/Networking/NetworkManager.cs
+++ b/Emby.Server.Implementations/Networking/NetworkManager.cs
@@ -7,8 +7,6 @@ using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Threading.Tasks;
using MediaBrowser.Common.Net;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Net;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Networking
@@ -55,10 +53,7 @@ namespace Emby.Server.Implementations.Networking
_macAddresses = null;
}
- if (NetworkChanged != null)
- {
- NetworkChanged(this, EventArgs.Empty);
- }
+ NetworkChanged?.Invoke(this, EventArgs.Empty);
}
public IPAddress[] GetLocalIpAddresses(bool ignoreVirtualInterface = true)
@@ -261,10 +256,10 @@ namespace Emby.Server.Implementations.Networking
return true;
}
- if (normalizedSubnet.IndexOf('/') != -1)
+ if (normalizedSubnet.Contains('/', StringComparison.Ordinal))
{
- var ipnetwork = IPNetwork.Parse(normalizedSubnet);
- if (ipnetwork.Contains(address))
+ var ipNetwork = IPNetwork.Parse(normalizedSubnet);
+ if (ipNetwork.Contains(address))
{
return true;
}
@@ -455,9 +450,9 @@ namespace Emby.Server.Implementations.Networking
public bool IsInSameSubnet(IPAddress address1, IPAddress address2, IPAddress subnetMask)
{
- IPAddress network1 = GetNetworkAddress(address1, subnetMask);
- IPAddress network2 = GetNetworkAddress(address2, subnetMask);
- return network1.Equals(network2);
+ IPAddress network1 = GetNetworkAddress(address1, subnetMask);
+ IPAddress network2 = GetNetworkAddress(address2, subnetMask);
+ return network1.Equals(network2);
}
private IPAddress GetNetworkAddress(IPAddress address, IPAddress subnetMask)
@@ -473,7 +468,7 @@ namespace Emby.Server.Implementations.Networking
byte[] broadcastAddress = new byte[ipAdressBytes.Length];
for (int i = 0; i < broadcastAddress.Length; i++)
{
- broadcastAddress[i] = (byte)(ipAdressBytes[i] & (subnetMaskBytes[i]));
+ broadcastAddress[i] = (byte)(ipAdressBytes[i] & subnetMaskBytes[i]);
}
return new IPAddress(broadcastAddress);
@@ -513,24 +508,5 @@ namespace Emby.Server.Implementations.Networking
return null;
}
-
- /// <summary>
- /// Gets the network shares.
- /// </summary>
- /// <param name="path">The path.</param>
- /// <returns>IEnumerable{NetworkShare}.</returns>
- public virtual IEnumerable<NetworkShare> GetNetworkShares(string path)
- {
- return new List<NetworkShare>();
- }
-
- /// <summary>
- /// Gets available devices within the domain
- /// </summary>
- /// <returns>PC's in the Domain</returns>
- public virtual IEnumerable<FileSystemEntryInfo> GetNetworkDevices()
- {
- return new List<FileSystemEntryInfo>();
- }
}
}
diff --git a/Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs b/Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs
index cad66a80f..2dfe59088 100644
--- a/Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs
+++ b/Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs
@@ -62,7 +62,6 @@ namespace Emby.Server.Implementations.Playlists
return null;
})
.Where(i => i != null)
- .OrderBy(i => Guid.NewGuid())
.GroupBy(x => x.Id)
.Select(x => x.First())
.ToList();
@@ -84,7 +83,7 @@ namespace Emby.Server.Implementations.Playlists
{
Genres = new[] { item.Name },
IncludeItemTypes = new[] { typeof(MusicAlbum).Name, typeof(MusicVideo).Name, typeof(Audio).Name },
- OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending) },
+ OrderBy = new[] { (ItemSortBy.Random, SortOrder.Ascending) },
Limit = 4,
Recursive = true,
ImageTypes = new[] { ImageType.Primary },
@@ -108,7 +107,7 @@ namespace Emby.Server.Implementations.Playlists
{
Genres = new[] { item.Name },
IncludeItemTypes = new[] { typeof(Series).Name, typeof(Movie).Name },
- OrderBy = new[] { new ValueTuple<string, SortOrder>(ItemSortBy.Random, SortOrder.Ascending) },
+ OrderBy = new[] { (ItemSortBy.Random, SortOrder.Ascending) },
Limit = 4,
Recursive = true,
ImageTypes = new[] { ImageType.Primary },
diff --git a/Emby.Server.Implementations/Playlists/PlaylistManager.cs b/Emby.Server.Implementations/Playlists/PlaylistManager.cs
index 0f58e43ed..b26f4026c 100644
--- a/Emby.Server.Implementations/Playlists/PlaylistManager.cs
+++ b/Emby.Server.Implementations/Playlists/PlaylistManager.cs
@@ -56,10 +56,8 @@ namespace Emby.Server.Implementations.Playlists
{
var name = options.Name;
- var folderName = _fileSystem.GetValidFilename(name) + " [playlist]";
-
+ var folderName = _fileSystem.GetValidFilename(name);
var parentFolder = GetPlaylistsFolder(Guid.Empty);
-
if (parentFolder == null)
{
throw new ArgumentException();
@@ -253,11 +251,13 @@ namespace Emby.Server.Implementations.Playlists
SavePlaylistFile(playlist);
}
- _providerManager.QueueRefresh(playlist.Id, new MetadataRefreshOptions(new DirectoryService(_fileSystem))
- {
- ForceSave = true
-
- }, RefreshPriority.High);
+ _providerManager.QueueRefresh(
+ playlist.Id,
+ new MetadataRefreshOptions(new DirectoryService(_fileSystem))
+ {
+ ForceSave = true
+ },
+ RefreshPriority.High);
}
public void MoveItem(string playlistId, string entryId, int newIndex)
@@ -303,7 +303,8 @@ namespace Emby.Server.Implementations.Playlists
private void SavePlaylistFile(Playlist item)
{
- // This is probably best done as a metatata provider, but saving a file over itself will first require some core work to prevent this from happening when not needed
+ // this is probably best done as a metadata provider
+ // saving a file over itself will require some work to prevent this from happening when not needed
var playlistPath = item.Path;
var extension = Path.GetExtension(playlistPath);
@@ -335,12 +336,14 @@ namespace Emby.Server.Implementations.Playlists
{
entry.Duration = TimeSpan.FromTicks(child.RunTimeTicks.Value);
}
+
playlist.PlaylistEntries.Add(entry);
}
string text = new WplContent().ToText(playlist);
File.WriteAllText(playlistPath, text);
}
+
if (string.Equals(".zpl", extension, StringComparison.OrdinalIgnoreCase))
{
var playlist = new ZplPlaylist();
@@ -375,6 +378,7 @@ namespace Emby.Server.Implementations.Playlists
string text = new ZplContent().ToText(playlist);
File.WriteAllText(playlistPath, text);
}
+
if (string.Equals(".m3u", extension, StringComparison.OrdinalIgnoreCase))
{
var playlist = new M3uPlaylist();
@@ -398,12 +402,14 @@ namespace Emby.Server.Implementations.Playlists
{
entry.Duration = TimeSpan.FromTicks(child.RunTimeTicks.Value);
}
+
playlist.PlaylistEntries.Add(entry);
}
string text = new M3uContent().ToText(playlist);
File.WriteAllText(playlistPath, text);
}
+
if (string.Equals(".m3u8", extension, StringComparison.OrdinalIgnoreCase))
{
var playlist = new M3uPlaylist();
@@ -427,12 +433,14 @@ namespace Emby.Server.Implementations.Playlists
{
entry.Duration = TimeSpan.FromTicks(child.RunTimeTicks.Value);
}
+
playlist.PlaylistEntries.Add(entry);
}
string text = new M3u8Content().ToText(playlist);
File.WriteAllText(playlistPath, text);
}
+
if (string.Equals(".pls", extension, StringComparison.OrdinalIgnoreCase))
{
var playlist = new PlsPlaylist();
@@ -448,6 +456,7 @@ namespace Emby.Server.Implementations.Playlists
{
entry.Length = TimeSpan.FromTicks(child.RunTimeTicks.Value);
}
+
playlist.PlaylistEntries.Add(entry);
}
@@ -473,7 +482,7 @@ namespace Emby.Server.Implementations.Playlists
throw new ArgumentException("File absolute path was null or empty.", nameof(fileAbsolutePath));
}
- if (!folderPath.EndsWith(Path.DirectorySeparatorChar.ToString()))
+ if (!folderPath.EndsWith(Path.DirectorySeparatorChar))
{
folderPath = folderPath + Path.DirectorySeparatorChar;
}
@@ -481,7 +490,11 @@ namespace Emby.Server.Implementations.Playlists
var folderUri = new Uri(folderPath);
var fileAbsoluteUri = new Uri(fileAbsolutePath);
- if (folderUri.Scheme != fileAbsoluteUri.Scheme) { return fileAbsolutePath; } // path can't be made relative.
+ // path can't be made relative
+ if (folderUri.Scheme != fileAbsoluteUri.Scheme)
+ {
+ return fileAbsolutePath;
+ }
var relativeUri = folderUri.MakeRelativeUri(fileAbsoluteUri);
string relativePath = Uri.UnescapeDataString(relativeUri.ToString());
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs
index 72b524df0..f197734d4 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteTranscodeFileTask.cs
@@ -31,13 +31,13 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
}
/// <summary>
- /// Creates the triggers that define when the task will run
+ /// Creates the triggers that define when the task will run.
/// </summary>
/// <returns>IEnumerable{BaseTaskTrigger}.</returns>
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers() => new List<TaskTriggerInfo>();
/// <summary>
- /// Returns the task to be executed
+ /// Returns the task to be executed.
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <param name="progress">The progress.</param>
@@ -52,9 +52,8 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
return Task.CompletedTask;
}
-
/// <summary>
- /// Deletes the transcoded temp files from directory with a last write time less than a given date
+ /// Deletes the transcoded temp files from directory with a last write time less than a given date.
/// </summary>
/// <param name="cancellationToken">The task cancellation token.</param>
/// <param name="directory">The directory.</param>
diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs
index fe8deae59..909fffb1f 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs
@@ -52,7 +52,9 @@ namespace Emby.Server.Implementations.ScheduledTasks
{
progress.Report(0);
- var packagesToInstall = (await _installationManager.GetAvailablePluginUpdates(cancellationToken).ConfigureAwait(false)).ToList();
+ var packagesToInstall = await _installationManager.GetAvailablePluginUpdates(cancellationToken)
+ .ToListAsync(cancellationToken)
+ .ConfigureAwait(false);
progress.Report(10);
diff --git a/Emby.Server.Implementations/ServerApplicationPaths.cs b/Emby.Server.Implementations/ServerApplicationPaths.cs
index 4b8298abb..2f57c97a1 100644
--- a/Emby.Server.Implementations/ServerApplicationPaths.cs
+++ b/Emby.Server.Implementations/ServerApplicationPaths.cs
@@ -1,4 +1,3 @@
-using System;
using System.IO;
using Emby.Server.Implementations.AppBase;
using MediaBrowser.Controller;
@@ -10,8 +9,6 @@ namespace Emby.Server.Implementations
/// </summary>
public class ServerApplicationPaths : BaseApplicationPaths, IServerApplicationPaths
{
- private string _defaultTranscodePath;
- private string _transcodePath;
private string _internalMetadataPath;
/// <summary>
@@ -23,7 +20,8 @@ namespace Emby.Server.Implementations
string configurationDirectoryPath,
string cacheDirectoryPath,
string webDirectoryPath)
- : base(programDataPath,
+ : base(
+ programDataPath,
logDirectoryPath,
configurationDirectoryPath,
cacheDirectoryPath,
@@ -31,8 +29,6 @@ namespace Emby.Server.Implementations
{
}
- public string ApplicationResourcesPath { get; } = AppContext.BaseDirectory;
-
/// <summary>
/// Gets the path to the base root media directory.
/// </summary>
@@ -46,17 +42,12 @@ namespace Emby.Server.Implementations
public string DefaultUserViewsPath => Path.Combine(RootFolderPath, "default");
/// <summary>
- /// Gets the path to localization data.
- /// </summary>
- /// <value>The localization path.</value>
- public string LocalizationPath => Path.Combine(ProgramDataPath, "localization");
-
- /// <summary>
/// Gets the path to the People directory.
/// </summary>
/// <value>The people path.</value>
public string PeoplePath => Path.Combine(InternalMetadataPath, "People");
+ /// <inheritdoc />
public string ArtistsPath => Path.Combine(InternalMetadataPath, "artists");
/// <summary>
@@ -107,12 +98,14 @@ namespace Emby.Server.Implementations
/// <value>The user configuration directory path.</value>
public string UserConfigurationDirectoryPath => Path.Combine(ConfigurationDirectoryPath, "users");
+ /// <inheritdoc />
public string InternalMetadataPath
{
get => _internalMetadataPath ?? (_internalMetadataPath = Path.Combine(DataPath, "metadata"));
set => _internalMetadataPath = value;
}
+ /// <inheritdoc />
public string VirtualInternalMetadataPath { get; } = "%MetadataPath%";
}
}
diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs
index d1392e162..b1d513dd4 100644
--- a/Emby.Server.Implementations/Session/SessionManager.cs
+++ b/Emby.Server.Implementations/Session/SessionManager.cs
@@ -667,12 +667,9 @@ namespace Emby.Server.Implementations.Session
data.PlayCount++;
data.LastPlayedDate = DateTime.UtcNow;
- if (item.SupportsPlayedStatus)
+ if (item.SupportsPlayedStatus && !item.SupportsPositionTicksResume)
{
- if (!(item is Video))
- {
- data.Played = true;
- }
+ data.Played = true;
}
else
{
@@ -769,7 +766,6 @@ namespace Emby.Server.Implementations.Session
{
_userDataManager.SaveUserData(user, item, data, UserDataSaveReason.PlaybackProgress, CancellationToken.None);
}
-
}
private static bool UpdatePlaybackSettings(User user, PlaybackProgressInfo info, UserItemData data)
@@ -1061,7 +1057,7 @@ namespace Emby.Server.Implementations.Session
var session = GetSessionToRemoteControl(sessionId);
- var user = !session.UserId.Equals(Guid.Empty) ? _userManager.GetUserById(session.UserId) : null;
+ var user = session.UserId == Guid.Empty ? null : _userManager.GetUserById(session.UserId);
List<BaseItem> items;
@@ -1086,7 +1082,7 @@ namespace Emby.Server.Implementations.Session
if (command.PlayCommand == PlayCommand.PlayShuffle)
{
- items = items.OrderBy(i => Guid.NewGuid()).ToList();
+ items.Shuffle();
command.PlayCommand = PlayCommand.PlayNow;
}
@@ -1100,28 +1096,27 @@ namespace Emby.Server.Implementations.Session
}
}
- if (user != null && command.ItemIds.Length == 1 && user.Configuration.EnableNextEpisodeAutoPlay)
+ if (user != null
+ && command.ItemIds.Length == 1
+ && user.Configuration.EnableNextEpisodeAutoPlay
+ && _libraryManager.GetItemById(command.ItemIds[0]) is Episode episode)
{
- var episode = _libraryManager.GetItemById(command.ItemIds[0]) as Episode;
- if (episode != null)
+ var series = episode.Series;
+ if (series != null)
{
- var series = episode.Series;
- if (series != null)
+ var episodes = series.GetEpisodes(
+ user,
+ new DtoOptions(false)
+ {
+ EnableImages = false
+ })
+ .Where(i => !i.IsVirtualItem)
+ .SkipWhile(i => i.Id != episode.Id)
+ .ToList();
+
+ if (episodes.Count > 0)
{
- var episodes = series.GetEpisodes(
- user,
- new DtoOptions(false)
- {
- EnableImages = false
- })
- .Where(i => !i.IsVirtualItem)
- .SkipWhile(i => i.Id != episode.Id)
- .ToList();
-
- if (episodes.Count > 0)
- {
- command.ItemIds = episodes.Select(i => i.Id).ToArray();
- }
+ command.ItemIds = episodes.Select(i => i.Id).ToArray();
}
}
}
@@ -1146,7 +1141,7 @@ namespace Emby.Server.Implementations.Session
if (item == null)
{
_logger.LogError("A non-existant item Id {0} was passed into TranslateItemForPlayback", id);
- return new List<BaseItem>();
+ return Array.Empty<BaseItem>();
}
if (item is IItemByName byName)
@@ -1164,7 +1159,7 @@ namespace Emby.Server.Implementations.Session
}
},
IsVirtualItem = false,
- OrderBy = new ValueTuple<string, SortOrder>[] { new ValueTuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending) }
+ OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) }
});
}
@@ -1185,12 +1180,11 @@ namespace Emby.Server.Implementations.Session
}
},
IsVirtualItem = false,
- OrderBy = new ValueTuple<string, SortOrder>[] { new ValueTuple<string, SortOrder>(ItemSortBy.SortName, SortOrder.Ascending) }
-
+ OrderBy = new[] { (ItemSortBy.SortName, SortOrder.Ascending) }
});
}
- return new List<BaseItem> { item };
+ return new[] { item };
}
private IEnumerable<BaseItem> TranslateItemForInstantMix(Guid id, User user)
@@ -1395,6 +1389,12 @@ namespace Emby.Server.Implementations.Session
}
}
+ if (user == null)
+ {
+ AuthenticationFailed?.Invoke(this, new GenericEventArgs<AuthenticationRequest>(request));
+ throw new SecurityException("Invalid user or password entered.");
+ }
+
if (enforcePassword)
{
user = await _userManager.AuthenticateUser(
@@ -1405,13 +1405,6 @@ namespace Emby.Server.Implementations.Session
true).ConfigureAwait(false);
}
- if (user == null)
- {
- AuthenticationFailed?.Invoke(this, new GenericEventArgs<AuthenticationRequest>(request));
-
- throw new SecurityException("Invalid user or password entered.");
- }
-
var token = GetAuthorizationToken(user, request.DeviceId, request.App, request.AppVersion, request.DeviceName);
var session = LogSessionActivity(
diff --git a/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs b/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs
index 690ba0be4..1781df8b5 100644
--- a/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs
+++ b/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
+using System.Net.Mime;
using MediaBrowser.Common.Net;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
@@ -14,9 +15,9 @@ namespace Emby.Server.Implementations.SocketSharp
{
public class WebSocketSharpRequest : IHttpRequest
{
- public const string FormUrlEncoded = "application/x-www-form-urlencoded";
- public const string MultiPartFormData = "multipart/form-data";
- public const string Soap11 = "text/xml; charset=utf-8";
+ private const string FormUrlEncoded = "application/x-www-form-urlencoded";
+ private const string MultiPartFormData = "multipart/form-data";
+ private const string Soap11 = "text/xml; charset=utf-8";
private string _remoteIp;
private Dictionary<string, object> _items;
@@ -77,7 +78,7 @@ namespace Emby.Server.Implementations.SocketSharp
get =>
_responseContentType
?? (_responseContentType = GetResponseContentType(Request));
- set => this._responseContentType = value;
+ set => _responseContentType = value;
}
public string PathInfo => Request.Path.Value;
@@ -90,7 +91,6 @@ namespace Emby.Server.Implementations.SocketSharp
public bool IsLocal => Request.HttpContext.Connection.LocalIpAddress.Equals(Request.HttpContext.Connection.RemoteIpAddress);
-
public string HttpMethod => Request.Method;
public string Verb => HttpMethod;
@@ -123,24 +123,29 @@ namespace Emby.Server.Implementations.SocketSharp
return specifiedContentType;
}
- const string serverDefaultContentType = "application/json";
+ const string ServerDefaultContentType = MediaTypeNames.Application.Json;
var acceptContentTypes = httpReq.Headers.GetCommaSeparatedValues(HeaderNames.Accept);
string defaultContentType = null;
if (HasAnyOfContentTypes(httpReq, FormUrlEncoded, MultiPartFormData))
{
- defaultContentType = serverDefaultContentType;
+ defaultContentType = ServerDefaultContentType;
}
var acceptsAnything = false;
var hasDefaultContentType = defaultContentType != null;
if (acceptContentTypes != null)
{
- foreach (var acceptsType in acceptContentTypes)
+ foreach (ReadOnlySpan<char> acceptsType in acceptContentTypes)
{
- // TODO: @bond move to Span when Span.Split lands
- // https://github.com/dotnet/corefx/issues/26528
- var contentType = acceptsType?.Split(';')[0].Trim();
+ ReadOnlySpan<char> contentType = acceptsType;
+ var index = contentType.IndexOf(';');
+ if (index != -1)
+ {
+ contentType = contentType.Slice(0, index);
+ }
+
+ contentType = contentType.Trim();
acceptsAnything = contentType.Equals("*/*", StringComparison.OrdinalIgnoreCase);
if (acceptsAnything)
@@ -157,7 +162,7 @@ namespace Emby.Server.Implementations.SocketSharp
}
else
{
- return serverDefaultContentType;
+ return ServerDefaultContentType;
}
}
}
@@ -168,7 +173,7 @@ namespace Emby.Server.Implementations.SocketSharp
}
// We could also send a '406 Not Acceptable', but this is allowed also
- return serverDefaultContentType;
+ return ServerDefaultContentType;
}
public static bool HasAnyOfContentTypes(HttpRequest request, params string[] contentTypes)
@@ -196,12 +201,12 @@ namespace Emby.Server.Implementations.SocketSharp
private static string GetQueryStringContentType(HttpRequest httpReq)
{
- ReadOnlySpan<char> format = httpReq.Query["format"].ToString().AsSpan();
+ ReadOnlySpan<char> format = httpReq.Query["format"].ToString();
if (format == null)
{
- const int formatMaxLength = 4;
- ReadOnlySpan<char> pi = httpReq.Path.ToString().AsSpan();
- if (pi == null || pi.Length <= formatMaxLength)
+ const int FormatMaxLength = 4;
+ ReadOnlySpan<char> pi = httpReq.Path.ToString();
+ if (pi == null || pi.Length <= FormatMaxLength)
{
return null;
}
@@ -212,18 +217,18 @@ namespace Emby.Server.Implementations.SocketSharp
}
format = LeftPart(pi, '/');
- if (format.Length > formatMaxLength)
+ if (format.Length > FormatMaxLength)
{
return null;
}
}
format = LeftPart(format, '.');
- if (format.Contains("json".AsSpan(), StringComparison.OrdinalIgnoreCase))
+ if (format.Contains("json", StringComparison.OrdinalIgnoreCase))
{
return "application/json";
}
- else if (format.Contains("xml".AsSpan(), StringComparison.OrdinalIgnoreCase))
+ else if (format.Contains("xml", StringComparison.OrdinalIgnoreCase))
{
return "application/xml";
}
diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs
index 1c5402268..c897036eb 100644
--- a/Emby.Server.Implementations/Updates/InstallationManager.cs
+++ b/Emby.Server.Implementations/Updates/InstallationManager.cs
@@ -1,10 +1,10 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
-using System.Globalization;
using System.IO;
using System.Linq;
using System.Net.Http;
+using System.Runtime.CompilerServices;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
@@ -141,8 +141,7 @@ namespace Emby.Server.Implementations.Updates
if (guid != Guid.Empty)
{
- var strGuid = guid.ToString("N", CultureInfo.InvariantCulture);
- availablePackages = availablePackages.Where(x => x.guid.Equals(strGuid, StringComparison.OrdinalIgnoreCase));
+ availablePackages = availablePackages.Where(x => Guid.Parse(x.guid) == guid);
}
return availablePackages;
@@ -180,7 +179,7 @@ namespace Emby.Server.Implementations.Updates
// Package not found.
if (package == null)
{
- return null;
+ return Enumerable.Empty<PackageVersionInfo>();
}
return GetCompatibleVersions(
@@ -190,19 +189,23 @@ namespace Emby.Server.Implementations.Updates
}
/// <inheritdoc />
- public async Task<IEnumerable<PackageVersionInfo>> GetAvailablePluginUpdates(CancellationToken cancellationToken = default)
+ public async IAsyncEnumerable<PackageVersionInfo> GetAvailablePluginUpdates([EnumeratorCancellation] CancellationToken cancellationToken = default)
{
var catalog = await GetAvailablePackages(cancellationToken).ConfigureAwait(false);
var systemUpdateLevel = _applicationHost.SystemUpdateLevel;
// Figure out what needs to be installed
- return _applicationHost.Plugins.Select(x =>
+ foreach (var plugin in _applicationHost.Plugins)
{
- var compatibleversions = GetCompatibleVersions(catalog, x.Name, x.Id, x.Version, systemUpdateLevel);
- return compatibleversions.FirstOrDefault(y => y.Version > x.Version);
- }).Where(x => x != null)
- .Where(x => !CompletedInstallations.Any(y => string.Equals(y.AssemblyGuid, x.guid, StringComparison.OrdinalIgnoreCase)));
+ var compatibleversions = GetCompatibleVersions(catalog, plugin.Name, plugin.Id, plugin.Version, systemUpdateLevel);
+ var version = compatibleversions.FirstOrDefault(y => y.Version > plugin.Version);
+ if (version != null
+ && !CompletedInstallations.Any(x => string.Equals(x.AssemblyGuid, version.guid, StringComparison.OrdinalIgnoreCase)))
+ {
+ yield return version;
+ }
+ }
}
/// <inheritdoc />
diff --git a/Emby.Server.Implementations/UserViews/DynamicImageProvider.cs b/Emby.Server.Implementations/UserViews/DynamicImageProvider.cs
index f48520443..78ac95f85 100644
--- a/Emby.Server.Implementations/UserViews/DynamicImageProvider.cs
+++ b/Emby.Server.Implementations/UserViews/DynamicImageProvider.cs
@@ -86,20 +86,17 @@ namespace Emby.Server.Implementations.UserViews
{
return items
.Where(i => i.HasImage(ImageType.Primary) || i.HasImage(ImageType.Thumb))
- .OrderBy(i => Guid.NewGuid())
.ToList();
}
return items
.Where(i => i.HasImage(ImageType.Primary))
- .OrderBy(i => Guid.NewGuid())
.ToList();
}
protected override bool Supports(BaseItem item)
{
- var view = item as UserView;
- if (view != null)
+ if (item is UserView view)
{
return IsUsingCollectionStrip(view);
}