Merge branch 'master' into warn17

This commit is contained in:
Bond-009
2020-03-11 20:26:43 +01:00
committed by GitHub
197 changed files with 2620 additions and 2176 deletions

View File

@@ -28,7 +28,7 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Activity
{
public class ActivityLogEntryPoint : IServerEntryPoint
public sealed class ActivityLogEntryPoint : IServerEntryPoint
{
private readonly ILogger _logger;
private readonly IInstallationManager _installationManager;
@@ -38,7 +38,6 @@ namespace Emby.Server.Implementations.Activity
private readonly ILocalizationManager _localization;
private readonly ISubtitleManager _subManager;
private readonly IUserManager _userManager;
private readonly IServerApplicationHost _appHost;
private readonly IDeviceManager _deviceManager;
/// <summary>
@@ -63,8 +62,7 @@ namespace Emby.Server.Implementations.Activity
ILocalizationManager localization,
IInstallationManager installationManager,
ISubtitleManager subManager,
IUserManager userManager,
IServerApplicationHost appHost)
IUserManager userManager)
{
_logger = logger;
_sessionManager = sessionManager;
@@ -75,7 +73,6 @@ namespace Emby.Server.Implementations.Activity
_installationManager = installationManager;
_subManager = subManager;
_userManager = userManager;
_appHost = appHost;
}
public Task RunAsync()
@@ -140,7 +137,7 @@ namespace Emby.Server.Implementations.Activity
CultureInfo.InvariantCulture,
_localization.GetLocalizedString("SubtitleDownloadFailureFromForItem"),
e.Provider,
Notifications.Notifications.GetItemName(e.Item)),
Emby.Notifications.NotificationEntryPoint.GetItemName(e.Item)),
Type = "SubtitleDownloadFailure",
ItemId = e.Item.Id.ToString("N", CultureInfo.InvariantCulture),
ShortOverview = e.Exception.Message
@@ -532,6 +529,7 @@ namespace Emby.Server.Implementations.Activity
private void CreateLogEntry(ActivityLogEntry entry)
=> _activityManager.Create(entry);
/// <inheritdoc />
public void Dispose()
{
_taskManager.TaskCompleted -= OnTaskCompleted;

View File

@@ -118,7 +118,6 @@ namespace Emby.Server.Implementations
public abstract class ApplicationHost : IServerApplicationHost, IDisposable
{
private SqliteUserRepository _userRepository;
private SqliteDisplayPreferencesRepository _displayPreferencesRepository;
/// <summary>
@@ -166,10 +165,9 @@ namespace Emby.Server.Implementations
public bool IsShuttingDown { get; private set; }
/// <summary>
/// Gets or sets the logger.
/// Gets the logger.
/// </summary>
/// <value>The logger.</value>
protected ILogger Logger { get; set; }
protected ILogger Logger { get; }
private IPlugin[] _plugins;
@@ -180,10 +178,9 @@ namespace Emby.Server.Implementations
public IReadOnlyList<IPlugin> Plugins => _plugins;
/// <summary>
/// Gets or sets the logger factory.
/// Gets the logger factory.
/// </summary>
/// <value>The logger factory.</value>
public ILoggerFactory LoggerFactory { get; protected set; }
protected ILoggerFactory LoggerFactory { get; }
/// <summary>
/// Gets or sets the application paths.
@@ -327,8 +324,6 @@ namespace Emby.Server.Implementations
private IMediaSourceManager MediaSourceManager { get; set; }
private readonly IConfiguration _configuration;
/// <summary>
/// Gets the installation manager.
/// </summary>
@@ -366,11 +361,8 @@ namespace Emby.Server.Implementations
IStartupOptions options,
IFileSystem fileSystem,
IImageEncoder imageEncoder,
INetworkManager networkManager,
IConfiguration configuration)
INetworkManager networkManager)
{
_configuration = configuration;
XmlSerializer = new MyXmlSerializer();
NetworkManager = networkManager;
@@ -586,7 +578,8 @@ namespace Emby.Server.Implementations
}
}
public async Task InitAsync(IServiceCollection serviceCollection)
/// <inheritdoc/>
public async Task InitAsync(IServiceCollection serviceCollection, IConfiguration startupConfig)
{
HttpPort = ServerConfigurationManager.Configuration.HttpServerPortNumber;
HttpsPort = ServerConfigurationManager.Configuration.HttpsPortNumber;
@@ -619,7 +612,7 @@ namespace Emby.Server.Implementations
DiscoverTypes();
await RegisterResources(serviceCollection).ConfigureAwait(false);
await RegisterResources(serviceCollection, startupConfig).ConfigureAwait(false);
ContentRoot = ServerConfigurationManager.Configuration.DashboardSourcePath;
if (string.IsNullOrEmpty(ContentRoot))
@@ -651,14 +644,14 @@ namespace Emby.Server.Implementations
var response = context.Response;
var localPath = context.Request.Path.ToString();
var req = new WebSocketSharpRequest(request, response, request.Path, Logger);
var req = new WebSocketSharpRequest(request, response, request.Path, LoggerFactory.CreateLogger<WebSocketSharpRequest>());
await HttpServer.RequestHandler(req, request.GetDisplayUrl(), request.Host.ToString(), localPath, context.RequestAborted).ConfigureAwait(false);
}
/// <summary>
/// Registers resources that classes will depend on
/// </summary>
protected async Task RegisterResources(IServiceCollection serviceCollection)
protected async Task RegisterResources(IServiceCollection serviceCollection, IConfiguration startupConfig)
{
serviceCollection.AddMemoryCache();
@@ -667,13 +660,10 @@ namespace Emby.Server.Implementations
serviceCollection.AddSingleton<IApplicationPaths>(ApplicationPaths);
serviceCollection.AddSingleton<IConfiguration>(_configuration);
serviceCollection.AddSingleton(JsonSerializer);
serviceCollection.AddSingleton(LoggerFactory);
serviceCollection.AddLogging();
serviceCollection.AddSingleton(Logger);
// TODO: Support for injecting ILogger should be deprecated in favour of ILogger<T> and this removed
serviceCollection.AddSingleton<ILogger>(Logger);
serviceCollection.AddSingleton(FileSystemManager);
serviceCollection.AddSingleton<TvDbClientManager>();
@@ -761,7 +751,7 @@ namespace Emby.Server.Implementations
ProcessFactory,
LocalizationManager,
() => SubtitleEncoder,
_configuration,
startupConfig,
StartupOptions.FFmpegPath);
serviceCollection.AddSingleton(MediaEncoder);
@@ -783,7 +773,7 @@ namespace Emby.Server.Implementations
this,
LoggerFactory.CreateLogger<HttpListenerHost>(),
ServerConfigurationManager,
_configuration,
startupConfig,
NetworkManager,
JsonSerializer,
XmlSerializer,
@@ -846,7 +836,10 @@ namespace Emby.Server.Implementations
UserViewManager = new UserViewManager(LibraryManager, LocalizationManager, UserManager, ChannelManager, LiveTvManager, ServerConfigurationManager);
serviceCollection.AddSingleton(UserViewManager);
NotificationManager = new NotificationManager(LoggerFactory, UserManager, ServerConfigurationManager);
NotificationManager = new NotificationManager(
LoggerFactory.CreateLogger<NotificationManager>(),
UserManager,
ServerConfigurationManager);
serviceCollection.AddSingleton(NotificationManager);
serviceCollection.AddSingleton<IDeviceDiscovery>(new DeviceDiscovery(ServerConfigurationManager));
@@ -1202,7 +1195,7 @@ namespace Emby.Server.Implementations
});
}
protected IHttpListener CreateHttpListener() => new WebSocketSharpListener(Logger);
protected IHttpListener CreateHttpListener() => new WebSocketSharpListener(LoggerFactory.CreateLogger<WebSocketSharpListener>());
private CertificateInfo GetCertificateInfo(bool generateCertificate)
{

View File

@@ -19,7 +19,11 @@ namespace Emby.Server.Implementations.Channels
private readonly ILogger _logger;
private readonly ILibraryManager _libraryManager;
public RefreshChannelsScheduledTask(IChannelManager channelManager, IUserManager userManager, ILogger logger, ILibraryManager libraryManager)
public RefreshChannelsScheduledTask(
IChannelManager channelManager,
IUserManager userManager,
ILogger<RefreshChannelsScheduledTask> logger,
ILibraryManager libraryManager)
{
_channelManager = channelManager;
_userManager = userManager;

View File

@@ -347,7 +347,10 @@ namespace Emby.Server.Implementations.Collections
private readonly IServerConfigurationManager _config;
private readonly ILogger _logger;
public CollectionManagerEntryPoint(ICollectionManager collectionManager, IServerConfigurationManager config, ILogger logger)
public CollectionManagerEntryPoint(
ICollectionManager collectionManager,
IServerConfigurationManager config,
ILogger<CollectionManagerEntryPoint> logger)
{
_collectionManager = (CollectionManager)collectionManager;
_config = config;

View File

@@ -8,7 +8,6 @@ namespace Emby.Server.Implementations
public static Dictionary<string, string> Configuration => new Dictionary<string, string>
{
{ "HttpListenerHost:DefaultRedirectPath", "web/index.html" },
{ "MusicBrainz:BaseUrl", "https://www.musicbrainz.org" },
{ FfmpegProbeSizeKey, "1G" },
{ FfmpegAnalyzeDurationKey, "200M" }
};

View File

@@ -14,7 +14,7 @@ namespace Emby.Server.Implementations.Data
private readonly ILibraryManager _libraryManager;
private readonly ILogger _logger;
public CleanDatabaseScheduledTask(ILibraryManager libraryManager, ILogger logger)
public CleanDatabaseScheduledTask(ILibraryManager libraryManager, ILogger<CleanDatabaseScheduledTask> logger)
{
_libraryManager = libraryManager;
_logger = logger;

View File

@@ -406,7 +406,10 @@ namespace Emby.Server.Implementations.Devices
private readonly IServerConfigurationManager _config;
private ILogger _logger;
public DeviceManagerEntryPoint(IDeviceManager deviceManager, IServerConfigurationManager config, ILogger logger)
public DeviceManagerEntryPoint(
IDeviceManager deviceManager,
IServerConfigurationManager config,
ILogger<DeviceManagerEntryPoint> logger)
{
_deviceManager = (DeviceManager)deviceManager;
_config = config;

View File

@@ -55,7 +55,12 @@ namespace Emby.Server.Implementations.EntryPoints
private readonly IProviderManager _providerManager;
public LibraryChangedNotifier(ILibraryManager libraryManager, ISessionManager sessionManager, IUserManager userManager, ILogger logger, IProviderManager providerManager)
public LibraryChangedNotifier(
ILibraryManager libraryManager,
ISessionManager sessionManager,
IUserManager userManager,
ILogger<LibraryChangedNotifier> logger,
IProviderManager providerManager)
{
_libraryManager = libraryManager;
_sessionManager = sessionManager;

View File

@@ -12,14 +12,18 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.EntryPoints
{
public class RecordingNotifier : IServerEntryPoint
public sealed class RecordingNotifier : IServerEntryPoint
{
private readonly ILiveTvManager _liveTvManager;
private readonly ISessionManager _sessionManager;
private readonly IUserManager _userManager;
private readonly ILogger _logger;
public RecordingNotifier(ISessionManager sessionManager, IUserManager userManager, ILogger logger, ILiveTvManager liveTvManager)
public RecordingNotifier(
ISessionManager sessionManager,
IUserManager userManager,
ILogger<RecordingNotifier> logger,
ILiveTvManager liveTvManager)
{
_sessionManager = sessionManager;
_userManager = userManager;
@@ -27,32 +31,33 @@ namespace Emby.Server.Implementations.EntryPoints
_liveTvManager = liveTvManager;
}
/// <inheritdoc />
public Task RunAsync()
{
_liveTvManager.TimerCancelled += _liveTvManager_TimerCancelled;
_liveTvManager.SeriesTimerCancelled += _liveTvManager_SeriesTimerCancelled;
_liveTvManager.TimerCreated += _liveTvManager_TimerCreated;
_liveTvManager.SeriesTimerCreated += _liveTvManager_SeriesTimerCreated;
_liveTvManager.TimerCancelled += OnLiveTvManagerTimerCancelled;
_liveTvManager.SeriesTimerCancelled += OnLiveTvManagerSeriesTimerCancelled;
_liveTvManager.TimerCreated += OnLiveTvManagerTimerCreated;
_liveTvManager.SeriesTimerCreated += OnLiveTvManagerSeriesTimerCreated;
return Task.CompletedTask;
}
private void _liveTvManager_SeriesTimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
private void OnLiveTvManagerSeriesTimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
{
SendMessage("SeriesTimerCreated", e.Argument);
}
private void _liveTvManager_TimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
private void OnLiveTvManagerTimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
{
SendMessage("TimerCreated", e.Argument);
}
private void _liveTvManager_SeriesTimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
private void OnLiveTvManagerSeriesTimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
{
SendMessage("SeriesTimerCancelled", e.Argument);
}
private void _liveTvManager_TimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
private void OnLiveTvManagerTimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
{
SendMessage("TimerCancelled", e.Argument);
}
@@ -63,11 +68,7 @@ namespace Emby.Server.Implementations.EntryPoints
try
{
await _sessionManager.SendMessageToUserSessions(users, name, info, CancellationToken.None);
}
catch (ObjectDisposedException)
{
// TODO Log exception or Investigate and properly fix.
await _sessionManager.SendMessageToUserSessions(users, name, info, CancellationToken.None).ConfigureAwait(false);
}
catch (Exception ex)
{
@@ -75,12 +76,13 @@ namespace Emby.Server.Implementations.EntryPoints
}
}
/// <inheritdoc />
public void Dispose()
{
_liveTvManager.TimerCancelled -= _liveTvManager_TimerCancelled;
_liveTvManager.SeriesTimerCancelled -= _liveTvManager_SeriesTimerCancelled;
_liveTvManager.TimerCreated -= _liveTvManager_TimerCreated;
_liveTvManager.SeriesTimerCreated -= _liveTvManager_SeriesTimerCreated;
_liveTvManager.TimerCancelled -= OnLiveTvManagerTimerCancelled;
_liveTvManager.SeriesTimerCancelled -= OnLiveTvManagerSeriesTimerCancelled;
_liveTvManager.TimerCreated -= OnLiveTvManagerTimerCreated;
_liveTvManager.SeriesTimerCreated -= OnLiveTvManagerSeriesTimerCreated;
}
}
}

View File

@@ -6,7 +6,6 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Tasks;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.EntryPoints
{
@@ -15,21 +14,17 @@ namespace Emby.Server.Implementations.EntryPoints
/// </summary>
public class RefreshUsersMetadata : IScheduledTask, IConfigurableScheduledTask
{
private readonly ILogger _logger;
/// <summary>
/// The user manager.
/// </summary>
private readonly IUserManager _userManager;
private IFileSystem _fileSystem;
private readonly IFileSystem _fileSystem;
/// <summary>
/// Initializes a new instance of the <see cref="RefreshUsersMetadata" /> class.
/// </summary>
public RefreshUsersMetadata(ILogger logger, IUserManager userManager, IFileSystem fileSystem)
public RefreshUsersMetadata(IUserManager userManager, IFileSystem fileSystem)
{
_logger = logger;
_userManager = userManager;
_fileSystem = fileSystem;
}

View File

@@ -3,37 +3,28 @@ using Emby.Server.Implementations.Browser;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Plugins;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.EntryPoints
{
/// <summary>
/// Class StartupWizard.
/// </summary>
public class StartupWizard : IServerEntryPoint
public sealed class StartupWizard : IServerEntryPoint
{
/// <summary>
/// The app host.
/// </summary>
private readonly IServerApplicationHost _appHost;
/// <summary>
/// The user manager.
/// </summary>
private readonly ILogger _logger;
private IServerConfigurationManager _config;
private readonly 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)
public StartupWizard(IServerApplicationHost appHost, IServerConfigurationManager config)
{
_appHost = appHost;
_logger = logger;
_config = config;
}

View File

@@ -3,8 +3,6 @@ using System.Threading.Tasks;
using Emby.Server.Implementations.Udp;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Serialization;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.EntryPoints
@@ -23,9 +21,7 @@ namespace Emby.Server.Implementations.EntryPoints
/// The logger.
/// </summary>
private readonly ILogger _logger;
private readonly ISocketFactory _socketFactory;
private readonly IServerApplicationHost _appHost;
private readonly IJsonSerializer _json;
/// <summary>
/// The UDP server.
@@ -64,7 +60,7 @@ namespace Emby.Server.Implementations.EntryPoints
_cancellationTokenSource.Cancel();
_udpServer.Dispose();
_cancellationTokenSource.Dispose();
_cancellationTokenSource = null;
_udpServer = null;

View File

@@ -12,39 +12,38 @@ using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Session;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.EntryPoints
{
public class UserDataChangeNotifier : IServerEntryPoint
public sealed class UserDataChangeNotifier : IServerEntryPoint
{
private const int UpdateDuration = 500;
private readonly ISessionManager _sessionManager;
private readonly ILogger _logger;
private readonly IUserDataManager _userDataManager;
private readonly IUserManager _userManager;
private readonly object _syncLock = new object();
private Timer UpdateTimer { get; set; }
private const int UpdateDuration = 500;
private readonly Dictionary<Guid, List<BaseItem>> _changedItems = new Dictionary<Guid, List<BaseItem>>();
public UserDataChangeNotifier(IUserDataManager userDataManager, ISessionManager sessionManager, ILogger logger, IUserManager userManager)
private readonly object _syncLock = new object();
private Timer _updateTimer;
public UserDataChangeNotifier(IUserDataManager userDataManager, ISessionManager sessionManager, IUserManager userManager)
{
_userDataManager = userDataManager;
_sessionManager = sessionManager;
_logger = logger;
_userManager = userManager;
}
public Task RunAsync()
{
_userDataManager.UserDataSaved += _userDataManager_UserDataSaved;
_userDataManager.UserDataSaved += OnUserDataManagerUserDataSaved;
return Task.CompletedTask;
}
void _userDataManager_UserDataSaved(object sender, UserDataSaveEventArgs e)
void OnUserDataManagerUserDataSaved(object sender, UserDataSaveEventArgs e)
{
if (e.SaveReason == UserDataSaveReason.PlaybackProgress)
{
@@ -53,14 +52,17 @@ namespace Emby.Server.Implementations.EntryPoints
lock (_syncLock)
{
if (UpdateTimer == null)
if (_updateTimer == null)
{
UpdateTimer = new Timer(UpdateTimerCallback, null, UpdateDuration,
Timeout.Infinite);
_updateTimer = new Timer(
UpdateTimerCallback,
null,
UpdateDuration,
Timeout.Infinite);
}
else
{
UpdateTimer.Change(UpdateDuration, Timeout.Infinite);
_updateTimer.Change(UpdateDuration, Timeout.Infinite);
}
if (!_changedItems.TryGetValue(e.UserId, out List<BaseItem> keys))
@@ -96,10 +98,10 @@ namespace Emby.Server.Implementations.EntryPoints
var task = SendNotifications(changes, CancellationToken.None);
if (UpdateTimer != null)
if (_updateTimer != null)
{
UpdateTimer.Dispose();
UpdateTimer = null;
_updateTimer.Dispose();
_updateTimer = null;
}
}
}
@@ -144,13 +146,13 @@ namespace Emby.Server.Implementations.EntryPoints
public void Dispose()
{
if (UpdateTimer != null)
if (_updateTimer != null)
{
UpdateTimer.Dispose();
UpdateTimer = null;
_updateTimer.Dispose();
_updateTimer = null;
}
_userDataManager.UserDataSaved -= _userDataManager_UserDataSaved;
_userDataManager.UserDataSaved -= OnUserDataManagerUserDataSaved;
}
}
}

View File

@@ -78,7 +78,7 @@ namespace Emby.Server.Implementations.HttpClientManager
if (!string.IsNullOrWhiteSpace(userInfo))
{
_logger.LogWarning("Found userInfo in url: {0} ... url: {1}", userInfo, url);
url = url.Replace(userInfo + '@', string.Empty);
url = url.Replace(userInfo + '@', string.Empty, StringComparison.Ordinal);
}
var request = new HttpRequestMessage(method, url);

View File

@@ -39,9 +39,9 @@ namespace Emby.Server.Implementations.HttpServer
private readonly Func<Type, Func<string, object>> _funcParseFn;
private readonly string _defaultRedirectPath;
private readonly string _baseUrlPrefix;
private readonly Dictionary<Type, Type> ServiceOperationsMap = new Dictionary<Type, Type>();
private IWebSocketListener[] _webSocketListeners = Array.Empty<IWebSocketListener>();
private readonly Dictionary<Type, Type> _serviceOperationsMap = new Dictionary<Type, Type>();
private readonly List<IWebSocketConnection> _webSocketConnections = new List<IWebSocketConnection>();
private IWebSocketListener[] _webSocketListeners = Array.Empty<IWebSocketListener>();
private bool _disposed = false;
public HttpListenerHost(
@@ -71,6 +71,8 @@ namespace Emby.Server.Implementations.HttpServer
ResponseFilters = Array.Empty<Action<IRequest, HttpResponse, object>>();
}
public event EventHandler<GenericEventArgs<IWebSocketConnection>> WebSocketConnected;
public Action<IRequest, HttpResponse, object>[] ResponseFilters { get; set; }
public static HttpListenerHost Instance { get; protected set; }
@@ -81,8 +83,6 @@ namespace Emby.Server.Implementations.HttpServer
public ServiceController ServiceController { get; private set; }
public event EventHandler<GenericEventArgs<IWebSocketConnection>> WebSocketConnected;
public object CreateInstance(Type type)
{
return _appHost.CreateInstance(type);
@@ -90,7 +90,7 @@ namespace Emby.Server.Implementations.HttpServer
private static string NormalizeUrlPath(string path)
{
if (path.StartsWith("/"))
if (path.Length > 0 && path[0] == '/')
{
// If the path begins with a leading slash, just return it as-is
return path;
@@ -130,13 +130,13 @@ namespace Emby.Server.Implementations.HttpServer
public Type GetServiceTypeByRequest(Type requestType)
{
ServiceOperationsMap.TryGetValue(requestType, out var serviceType);
_serviceOperationsMap.TryGetValue(requestType, out var serviceType);
return serviceType;
}
public void AddServiceInfo(Type serviceType, Type requestType)
{
ServiceOperationsMap[requestType] = serviceType;
_serviceOperationsMap[requestType] = serviceType;
}
private List<IHasRequestFilter> GetRequestFilterAttributes(Type requestDtoType)
@@ -198,7 +198,7 @@ namespace Emby.Server.Implementations.HttpServer
else
{
var inners = agg.InnerExceptions;
if (inners != null && inners.Count > 0)
if (inners.Count > 0)
{
return GetActualException(inners[0]);
}
@@ -361,7 +361,7 @@ namespace Emby.Server.Implementations.HttpServer
return true;
}
host = host ?? string.Empty;
host ??= string.Empty;
if (_networkManager.IsInPrivateAddressSpace(host))
{
@@ -432,7 +432,7 @@ namespace Emby.Server.Implementations.HttpServer
}
/// <summary>
/// Overridable method that can be used to implement a custom hnandler
/// Overridable method that can be used to implement a custom handler.
/// </summary>
public async Task RequestHandler(IHttpRequest httpReq, string urlString, string host, string localPath, CancellationToken cancellationToken)
{
@@ -491,7 +491,7 @@ namespace Emby.Server.Implementations.HttpServer
|| string.Equals(localPath, _baseUrlPrefix, StringComparison.OrdinalIgnoreCase)
|| string.Equals(localPath, "/", StringComparison.OrdinalIgnoreCase)
|| string.IsNullOrEmpty(localPath)
|| !localPath.StartsWith(_baseUrlPrefix))
|| !localPath.StartsWith(_baseUrlPrefix, StringComparison.OrdinalIgnoreCase))
{
// Always redirect back to the default path if the base prefix is invalid or missing
_logger.LogDebug("Normalizing a URL at {0}", localPath);
@@ -692,7 +692,10 @@ namespace Emby.Server.Implementations.HttpServer
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (_disposed)
{
return;
}
if (disposing)
{

View File

@@ -5,7 +5,9 @@ namespace Emby.Server.Implementations.IO
public class ExtendedFileSystemInfo
{
public bool IsHidden { get; set; }
public bool IsReadOnly { get; set; }
public bool Exists { get; set; }
}
}

View File

@@ -14,27 +14,29 @@ namespace Emby.Server.Implementations.IO
{
public class FileRefresher : IDisposable
{
private ILogger Logger { get; set; }
private ILibraryManager LibraryManager { get; set; }
private IServerConfigurationManager ConfigurationManager { get; set; }
private readonly List<string> _affectedPaths = new List<string>();
private Timer _timer;
private readonly object _timerLock = new object();
public string Path { get; private set; }
private readonly ILogger _logger;
private readonly ILibraryManager _libraryManager;
private readonly IServerConfigurationManager _configurationManager;
public event EventHandler<EventArgs> Completed;
private readonly List<string> _affectedPaths = new List<string>();
private readonly object _timerLock = new object();
private Timer _timer;
public FileRefresher(string path, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, ILogger logger)
{
logger.LogDebug("New file refresher created for {0}", path);
Path = path;
ConfigurationManager = configurationManager;
LibraryManager = libraryManager;
Logger = logger;
_configurationManager = configurationManager;
_libraryManager = libraryManager;
_logger = logger;
AddPath(path);
}
public event EventHandler<EventArgs> Completed;
public string Path { get; private set; }
private void AddAffectedPath(string path)
{
if (string.IsNullOrEmpty(path))
@@ -79,11 +81,11 @@ namespace Emby.Server.Implementations.IO
if (_timer == null)
{
_timer = new Timer(OnTimerCallback, null, TimeSpan.FromSeconds(ConfigurationManager.Configuration.LibraryMonitorDelay), TimeSpan.FromMilliseconds(-1));
_timer = new Timer(OnTimerCallback, null, TimeSpan.FromSeconds(_configurationManager.Configuration.LibraryMonitorDelay), TimeSpan.FromMilliseconds(-1));
}
else
{
_timer.Change(TimeSpan.FromSeconds(ConfigurationManager.Configuration.LibraryMonitorDelay), TimeSpan.FromMilliseconds(-1));
_timer.Change(TimeSpan.FromSeconds(_configurationManager.Configuration.LibraryMonitorDelay), TimeSpan.FromMilliseconds(-1));
}
}
}
@@ -92,7 +94,7 @@ namespace Emby.Server.Implementations.IO
{
lock (_timerLock)
{
Logger.LogDebug("Resetting file refresher from {0} to {1}", Path, path);
_logger.LogDebug("Resetting file refresher from {0} to {1}", Path, path);
Path = path;
AddAffectedPath(path);
@@ -115,7 +117,7 @@ namespace Emby.Server.Implementations.IO
paths = _affectedPaths.ToList();
}
Logger.LogDebug("Timer stopped.");
_logger.LogDebug("Timer stopped.");
DisposeTimer();
Completed?.Invoke(this, EventArgs.Empty);
@@ -126,7 +128,7 @@ namespace Emby.Server.Implementations.IO
}
catch (Exception ex)
{
Logger.LogError(ex, "Error processing directory changes");
_logger.LogError(ex, "Error processing directory changes");
}
}
@@ -146,7 +148,7 @@ namespace Emby.Server.Implementations.IO
continue;
}
Logger.LogInformation("{name} ({path}) will be refreshed.", item.Name, item.Path);
_logger.LogInformation("{name} ({path}) will be refreshed.", item.Name, item.Path);
try
{
@@ -157,11 +159,11 @@ namespace Emby.Server.Implementations.IO
// For now swallow and log.
// Research item: If an IOException occurs, the item may be in a disconnected state (media unavailable)
// Should we remove it from it's parent?
Logger.LogError(ex, "Error refreshing {name}", item.Name);
_logger.LogError(ex, "Error refreshing {name}", item.Name);
}
catch (Exception ex)
{
Logger.LogError(ex, "Error refreshing {name}", item.Name);
_logger.LogError(ex, "Error refreshing {name}", item.Name);
}
}
}
@@ -177,7 +179,7 @@ namespace Emby.Server.Implementations.IO
while (item == null && !string.IsNullOrEmpty(path))
{
item = LibraryManager.FindByPath(path, null);
item = _libraryManager.FindByPath(path, null);
path = System.IO.Path.GetDirectoryName(path);
}

View File

@@ -943,7 +943,6 @@ namespace Emby.Server.Implementations.Library
IncludeItemTypes = new[] { typeof(T).Name },
Name = name,
DtoOptions = options
}).Cast<MusicArtist>()
.OrderBy(i => i.IsAccessedByName ? 1 : 0)
.Cast<T>()
@@ -1079,7 +1078,7 @@ namespace Emby.Server.Implementations.Library
var innerProgress = new ActionableProgress<double>();
innerProgress.RegisterAction(pct => progress.Report(pct * pct * 0.96));
innerProgress.RegisterAction(pct => progress.Report(pct * 0.96));
// Validate the entire media library
await RootFolder.ValidateChildren(innerProgress, cancellationToken, new MetadataRefreshOptions(new DirectoryService(_fileSystem)), recursive: true).ConfigureAwait(false);

View File

@@ -27,7 +27,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.Audio
/// <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)
public MusicArtistResolver(
ILogger<MusicArtistResolver> logger,
IFileSystem fileSystem,
ILibraryManager libraryManager,
IServerConfigurationManager config)
{
_logger = logger;
_fileSystem = fileSystem;

View File

@@ -5,38 +5,33 @@ using System.IO;
using System.Linq;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Playlists;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.LocalMetadata.Savers;
using MediaBrowser.Model.Entities;
namespace Emby.Server.Implementations.Library.Resolvers
{
/// <summary>
/// <see cref="IItemResolver"/> for <see cref="Playlist"/> library items.
/// </summary>
public class PlaylistResolver : FolderResolver<Playlist>
{
private string[] SupportedCollectionTypes = new string[] {
private string[] _musicPlaylistCollectionTypes = new string[] {
string.Empty,
CollectionType.Music
};
/// <summary>
/// Resolves the specified args.
/// </summary>
/// <param name="args">The args.</param>
/// <returns>BoxSet.</returns>
/// <inheritdoc/>
protected override Playlist Resolve(ItemResolveArgs args)
{
// It's a boxset if all of the following conditions are met:
// Is a Directory
// Contains [playlist] in the path
if (args.IsDirectory)
{
var filename = Path.GetFileName(args.Path);
if (string.IsNullOrEmpty(filename))
{
return null;
}
if (filename.IndexOf("[playlist]", StringComparison.OrdinalIgnoreCase) != -1)
// It's a boxset if the path is a directory with [playlist] in it's the name
// TODO: Should this use Path.GetDirectoryName() instead?
bool isBoxSet = Path.GetFileName(args.Path)
?.Contains("[playlist]", StringComparison.OrdinalIgnoreCase)
?? false;
if (isBoxSet)
{
return new Playlist
{
@@ -44,21 +39,32 @@ namespace Emby.Server.Implementations.Library.Resolvers
Name = Path.GetFileName(args.Path).Replace("[playlist]", string.Empty, StringComparison.OrdinalIgnoreCase).Trim()
};
}
}
else
{
if (SupportedCollectionTypes.Contains(args.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase))
// It's a directory-based playlist if the directory contains a playlist file
var filePaths = Directory.EnumerateFiles(args.Path);
if (filePaths.Any(f => f.EndsWith(PlaylistXmlSaver.DefaultPlaylistFilename, StringComparison.OrdinalIgnoreCase)))
{
var extension = Path.GetExtension(args.Path);
if (Playlist.SupportedExtensions.Contains(extension ?? string.Empty, StringComparer.OrdinalIgnoreCase))
return new Playlist
{
return new Playlist
{
Path = args.Path,
Name = Path.GetFileNameWithoutExtension(args.Path),
IsInMixedFolder = true
};
}
Path = args.Path,
Name = Path.GetFileName(args.Path)
};
}
}
// Check if this is a music playlist file
// It should have the correct collection type and a supported file extension
else if (_musicPlaylistCollectionTypes.Contains(args.CollectionType ?? string.Empty, StringComparer.OrdinalIgnoreCase))
{
var extension = Path.GetExtension(args.Path);
if (Playlist.SupportedExtensions.Contains(extension ?? string.Empty, StringComparer.OrdinalIgnoreCase))
{
return new Playlist
{
Path = args.Path,
Name = Path.GetFileNameWithoutExtension(args.Path),
IsInMixedFolder = true
};
}
}

View File

@@ -25,7 +25,11 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
/// <param name="libraryManager">The library manager.</param>
/// <param name="localization">The localization</param>
/// <param name="logger">The logger</param>
public SeasonResolver(IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization, ILogger logger)
public SeasonResolver(
IServerConfigurationManager config,
ILibraryManager libraryManager,
ILocalizationManager localization,
ILogger<SeasonResolver> logger)
{
_config = config;
_libraryManager = libraryManager;

View File

@@ -30,7 +30,7 @@ namespace Emby.Server.Implementations.Library.Resolvers.TV
/// <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)
public SeriesResolver(IFileSystem fileSystem, ILogger<SeriesResolver> logger, ILibraryManager libraryManager)
{
_fileSystem = fileSystem;
_logger = logger;

View File

@@ -25,7 +25,10 @@ namespace Emby.Server.Implementations.Library.Validators
/// <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)
public ArtistsPostScanTask(
ILibraryManager libraryManager,
ILogger<ArtistsPostScanTask> logger,
IItemRepository itemRepo)
{
_libraryManager = libraryManager;
_logger = logger;

View File

@@ -25,7 +25,10 @@ namespace Emby.Server.Implementations.Library.Validators
/// <param name="libraryManager">The library manager.</param>
/// <param name="logger">The logger.</param>
/// <param name="itemRepo">The item repository.</param>
public GenresPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
public GenresPostScanTask(
ILibraryManager libraryManager,
ILogger<GenresPostScanTask> logger,
IItemRepository itemRepo)
{
_libraryManager = libraryManager;
_logger = logger;

View File

@@ -25,7 +25,10 @@ namespace Emby.Server.Implementations.Library.Validators
/// <param name="libraryManager">The library manager.</param>
/// <param name="logger">The logger.</param>
/// <param name="itemRepo">The item repository.</param>
public MusicGenresPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
public MusicGenresPostScanTask(
ILibraryManager libraryManager,
ILogger<MusicGenresPostScanTask> logger,
IItemRepository itemRepo)
{
_libraryManager = libraryManager;
_logger = logger;

View File

@@ -26,7 +26,10 @@ namespace Emby.Server.Implementations.Library.Validators
/// <param name="libraryManager">The library manager.</param>
/// <param name="logger">The logger.</param>
/// <param name="itemRepo">The item repository.</param>
public StudiosPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo)
public StudiosPostScanTask(
ILibraryManager libraryManager,
ILogger<StudiosPostScanTask> logger,
IItemRepository itemRepo)
{
_libraryManager = libraryManager;
_logger = logger;

View File

@@ -1,3 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System;
using System.IO;
using System.Net.Http;

View File

@@ -29,7 +29,6 @@ using MediaBrowser.Model.Diagnostics;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Events;
using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.MediaInfo;
@@ -80,7 +79,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
IServerApplicationHost appHost,
IStreamHelper streamHelper,
IMediaSourceManager mediaSourceManager,
ILogger logger,
ILogger<EmbyTV> logger,
IJsonSerializer jsonSerializer,
IHttpClient httpClient,
IServerConfigurationManager config,

View File

@@ -1,3 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System;
using System.Collections.Generic;
using System.Globalization;

View File

@@ -1,3 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System.Threading.Tasks;
using MediaBrowser.Controller.Plugins;
@@ -5,11 +8,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
public class EntryPoint : IServerEntryPoint
{
/// <inheritdoc />
public Task RunAsync()
{
return EmbyTV.Current.Start();
}
/// <inheritdoc />
public void Dispose()
{
}

View File

@@ -1,3 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System;
using System.Threading;
using System.Threading.Tasks;

View File

@@ -1,3 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System;
using System.Collections.Generic;
using System.IO;

View File

@@ -1,3 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System;
using System.Globalization;
using MediaBrowser.Controller.LiveTv;
@@ -21,7 +24,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
if (info.SeasonNumber.HasValue && info.EpisodeNumber.HasValue)
{
name += string.Format(" S{0}E{1}", info.SeasonNumber.Value.ToString("00", CultureInfo.InvariantCulture), info.EpisodeNumber.Value.ToString("00", CultureInfo.InvariantCulture));
name += string.Format(
CultureInfo.InvariantCulture,
" S{0}E{1}",
info.SeasonNumber.Value.ToString("00", CultureInfo.InvariantCulture),
info.EpisodeNumber.Value.ToString("00", CultureInfo.InvariantCulture));
addHyphen = false;
}
else if (info.OriginalAirDate.HasValue)
@@ -32,7 +39,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
}
else
{
name += " " + info.OriginalAirDate.Value.ToLocalTime().ToString("yyyy-MM-dd");
name += " " + info.OriginalAirDate.Value.ToLocalTime().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
}
}
else
@@ -67,14 +74,15 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
date = date.ToLocalTime();
return string.Format("{0}_{1}_{2}_{3}_{4}_{5}",
return string.Format(
CultureInfo.InvariantCulture,
"{0}_{1}_{2}_{3}_{4}_{5}",
date.Year.ToString("0000", CultureInfo.InvariantCulture),
date.Month.ToString("00", CultureInfo.InvariantCulture),
date.Day.ToString("00", CultureInfo.InvariantCulture),
date.Hour.ToString("00", CultureInfo.InvariantCulture),
date.Minute.ToString("00", CultureInfo.InvariantCulture),
date.Second.ToString("00", CultureInfo.InvariantCulture)
);
date.Second.ToString("00", CultureInfo.InvariantCulture));
}
}
}

View File

@@ -1,3 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Model.Serialization;
@@ -12,6 +15,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
}
/// <inheritdoc />
public override void Add(SeriesTimerInfo item)
{
if (string.IsNullOrEmpty(item.Id))

View File

@@ -1,3 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System;
using System.Collections.Concurrent;
using System.Globalization;

View File

@@ -1,3 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -30,7 +33,11 @@ namespace Emby.Server.Implementations.LiveTv.Listings
private const string ApiUrl = "https://json.schedulesdirect.org/20141201";
public SchedulesDirect(ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IApplicationHost appHost)
public SchedulesDirect(
ILogger<SchedulesDirect> logger,
IJsonSerializer jsonSerializer,
IHttpClient httpClient,
IApplicationHost appHost)
{
_logger = logger;
_jsonSerializer = jsonSerializer;

View File

@@ -1,3 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -31,7 +34,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
public XmlTvListingsProvider(
IServerConfigurationManager config,
IHttpClient httpClient,
ILogger logger,
ILogger<XmlTvListingsProvider> logger,
IFileSystem fileSystem,
IZipClient zipClient)
{
@@ -91,12 +94,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings
{
using (var gzStream = new GZipStream(stream, CompressionMode.Decompress))
{
await gzStream.CopyToAsync(fileStream).ConfigureAwait(false);
await gzStream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false);
}
}
else
{
await stream.CopyToAsync(fileStream).ConfigureAwait(false);
await stream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false);
}
}

View File

@@ -1,3 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System.Collections.Generic;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Model.LiveTv;

View File

@@ -1,3 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System;
using System.Globalization;
using System.Linq;

View File

@@ -1,4 +1,5 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System;
using System.Collections.Generic;

View File

@@ -1,52 +1,48 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.MediaInfo;
using MediaBrowser.Model.Serialization;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.LiveTv
{
public class LiveTvMediaSourceProvider : IMediaSourceProvider
{
// Do not use a pipe here because Roku http requests to the server will fail, without any explicit error message.
private const char StreamIdDelimeter = '_';
private const string StreamIdDelimeterString = "_";
private readonly ILiveTvManager _liveTvManager;
private readonly IJsonSerializer _jsonSerializer;
private readonly ILogger _logger;
private readonly IMediaSourceManager _mediaSourceManager;
private readonly IMediaEncoder _mediaEncoder;
private readonly IServerApplicationHost _appHost;
private IApplicationPaths _appPaths;
public LiveTvMediaSourceProvider(ILiveTvManager liveTvManager, IApplicationPaths appPaths, IJsonSerializer jsonSerializer, ILoggerFactory loggerFactory, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder, IServerApplicationHost appHost)
public LiveTvMediaSourceProvider(ILiveTvManager liveTvManager, ILogger<LiveTvMediaSourceProvider> logger, IMediaSourceManager mediaSourceManager, IServerApplicationHost appHost)
{
_liveTvManager = liveTvManager;
_jsonSerializer = jsonSerializer;
_logger = logger;
_mediaSourceManager = mediaSourceManager;
_mediaEncoder = mediaEncoder;
_appHost = appHost;
_logger = loggerFactory.CreateLogger(GetType().Name);
_appPaths = appPaths;
}
public Task<IEnumerable<MediaSourceInfo>> GetMediaSources(BaseItem item, CancellationToken cancellationToken)
{
var baseItem = (BaseItem)item;
if (baseItem.SourceType == SourceType.LiveTV)
if (item.SourceType == SourceType.LiveTV)
{
var activeRecordingInfo = _liveTvManager.GetActiveRecordingInfo(item.Path);
if (string.IsNullOrEmpty(baseItem.Path) || activeRecordingInfo != null)
if (string.IsNullOrEmpty(item.Path) || activeRecordingInfo != null)
{
return GetMediaSourcesInternal(item, activeRecordingInfo, cancellationToken);
}
@@ -55,10 +51,6 @@ namespace Emby.Server.Implementations.LiveTv
return Task.FromResult<IEnumerable<MediaSourceInfo>>(Array.Empty<MediaSourceInfo>());
}
// Do not use a pipe here because Roku http requests to the server will fail, without any explicit error message.
private const char StreamIdDelimeter = '_';
private const string StreamIdDelimeterString = "_";
private async Task<IEnumerable<MediaSourceInfo>> GetMediaSourcesInternal(BaseItem item, ActiveRecordingInfo activeRecordingInfo, CancellationToken cancellationToken)
{
IEnumerable<MediaSourceInfo> sources;
@@ -91,7 +83,7 @@ namespace Emby.Server.Implementations.LiveTv
foreach (var source in list)
{
source.Type = MediaSourceType.Default;
source.BufferMs = source.BufferMs ?? 1500;
source.BufferMs ??= 1500;
if (source.RequiresOpening || forceRequireOpening)
{
@@ -100,11 +92,14 @@ namespace Emby.Server.Implementations.LiveTv
if (source.RequiresOpening)
{
var openKeys = new List<string>();
openKeys.Add(item.GetType().Name);
openKeys.Add(item.Id.ToString("N", CultureInfo.InvariantCulture));
openKeys.Add(source.Id ?? string.Empty);
source.OpenToken = string.Join(StreamIdDelimeterString, openKeys.ToArray());
var openKeys = new List<string>
{
item.GetType().Name,
item.Id.ToString("N", CultureInfo.InvariantCulture),
source.Id ?? string.Empty
};
source.OpenToken = string.Join(StreamIdDelimeterString, openKeys);
}
// Dummy this up so that direct play checks can still run
@@ -114,11 +109,12 @@ namespace Emby.Server.Implementations.LiveTv
}
}
_logger.LogDebug("MediaSources: {0}", _jsonSerializer.SerializeToString(list));
_logger.LogDebug("MediaSources: {@MediaSources}", list);
return list;
}
/// <inheritdoc />
public async Task<ILiveStream> OpenMediaSource(string openToken, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken)
{
var keys = openToken.Split(new[] { StreamIdDelimeter }, 3);

View File

@@ -1,3 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;

View File

@@ -1,3 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -36,7 +39,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
public HdHomerunHost(
IServerConfigurationManager config,
ILogger logger,
ILogger<HdHomerunHost> logger,
IJsonSerializer jsonSerializer,
IFileSystem fileSystem,
IHttpClient httpClient,

View File

@@ -1,3 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System;
using System.Buffers;
using System.Collections.Generic;

View File

@@ -1,3 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System;
using System.Collections.Generic;
using System.IO;

View File

@@ -1,3 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System;
using System.Collections.Generic;
using System.Globalization;

View File

@@ -1,3 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System;
using System.Collections.Generic;
using System.Globalization;

View File

@@ -1,3 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System;
using System.Collections.Generic;
using System.Globalization;

View File

@@ -1,3 +1,6 @@
#pragma warning disable CS1591
#pragma warning disable SA1600
using System;
using System.Collections.Generic;
using System.IO;

View File

@@ -2,22 +2,22 @@
"Albums": "ألبومات",
"AppDeviceValues": "تطبيق: {0}, جهاز: {1}",
"Application": "التطبيق",
"Artists": "الفنان",
"Artists": "الفنانين",
"AuthenticationSucceededWithUserName": "{0} سجل الدخول بنجاح",
"Books": "كتب",
"CameraImageUploadedFrom": "صورة كاميرا جديدة تم رفعها من {0}",
"Channels": "القنوات",
"ChapterNameValue": "الباب {0}",
"ChapterNameValue": "فصل {0}",
"Collections": "مجموعات",
"DeviceOfflineWithName": "تم قطع اتصال {0}",
"DeviceOfflineWithName": "قُطِع الاتصال بـ{0}",
"DeviceOnlineWithName": "{0} متصل",
"FailedLoginAttemptWithUserName": "عملية تسجيل الدخول فشلت من {0}",
"Favorites": "التفضيلات",
"Favorites": "المفضلة",
"Folders": "المجلدات",
"Genres": "أنواع الأفلام",
"Genres": "الأنواع",
"HeaderAlbumArtists": "فناني الألبومات",
"HeaderCameraUploads": "تحميلات الكاميرا",
"HeaderContinueWatching": "استئناف المشاهدة",
"HeaderContinueWatching": "استئناف",
"HeaderFavoriteAlbums": "الألبومات المفضلة",
"HeaderFavoriteArtists": "الفنانون المفضلون",
"HeaderFavoriteEpisodes": "الحلقات المفضلة",
@@ -31,28 +31,28 @@
"ItemAddedWithName": "تم إضافة {0} للمكتبة",
"ItemRemovedWithName": "تم إزالة {0} من المكتبة",
"LabelIpAddressValue": "عنوان الآي بي: {0}",
"LabelRunningTimeValue": "وقت التشغيل: {0}",
"LabelRunningTimeValue": "المدة: {0}",
"Latest": "الأحدث",
"MessageApplicationUpdated": "لقد تم تحديث خادم أمبي",
"MessageApplicationUpdated": "لقد تم تحديث خادم Jellyfin",
"MessageApplicationUpdatedTo": "تم تحديث سيرفر Jellyfin الى {0}",
"MessageNamedServerConfigurationUpdatedWithValue": "تم تحديث إعدادات الخادم في قسم {0}",
"MessageServerConfigurationUpdated": "تم تحديث إعدادات الخادم",
"MixedContent": "محتوى مخلوط",
"MixedContent": "محتوى مختلط",
"Movies": "الأفلام",
"Music": "الموسيقى",
"MusicVideos": "الفيديوهات الموسيقية",
"NameInstallFailed": "فشل التثبيت {0}",
"NameSeasonNumber": "الموسم {0}",
"NameSeasonUnknown": "الموسم غير معروف",
"NewVersionIsAvailable": "نسخة حديثة من سيرفر Jellyfin متوفرة للتحميل .",
"NewVersionIsAvailable": "نسخة جديدة من سيرفر Jellyfin متوفرة للتحميل.",
"NotificationOptionApplicationUpdateAvailable": "يوجد تحديث للتطبيق",
"NotificationOptionApplicationUpdateInstalled": "تم تحديث التطبيق",
"NotificationOptionAudioPlayback": "بدأ تشغيل المقطع الصوتي",
"NotificationOptionAudioPlaybackStopped": "تم إيقاف تشغيل المقطع الصوتي",
"NotificationOptionCameraImageUploaded": "تم رقع صورة الكاميرا",
"NotificationOptionCameraImageUploaded": "تم رفع صورة الكاميرا",
"NotificationOptionInstallationFailed": "فشل في التثبيت",
"NotificationOptionNewLibraryContent": "تم إضافة محتوى جديد",
"NotificationOptionPluginError": "فشل في الملحق",
"NotificationOptionNewLibraryContent": "أُضِيفَ محتوى جديد",
"NotificationOptionPluginError": "فشل في الـPlugin",
"NotificationOptionPluginInstalled": "تم تثبيت الملحق",
"NotificationOptionPluginUninstalled": "تمت إزالة الملحق",
"NotificationOptionPluginUpdateInstalled": "تم تثبيت تحديثات الملحق",

View File

@@ -3,7 +3,7 @@
"AppDeviceValues": "App: {0}, Enhed: {1}",
"Application": "Applikation",
"Artists": "Kunstnere",
"AuthenticationSucceededWithUserName": "{0} bekræftet med succes",
"AuthenticationSucceededWithUserName": "{0} succesfuldt autentificeret",
"Books": "Bøger",
"CameraImageUploadedFrom": "Et nyt kamerabillede er blevet uploadet fra {0}",
"Channels": "Kanaler",

View File

@@ -1,15 +1,15 @@
{
"Albums": "Alben",
"AppDeviceValues": "App: {0}, Gerät: {1}",
"Application": "Anwendung",
"AppDeviceValues": "Anw: {0}, Gerät: {1}",
"Application": "Programm",
"Artists": "Interpreten",
"AuthenticationSucceededWithUserName": "{0} hat sich erfolgreich angemeldet",
"Books": "Bücher",
"CameraImageUploadedFrom": "Ein neues Foto wurde hochgeladen von {0}",
"CameraImageUploadedFrom": "Ein neues Foto wurde von {0} hochgeladen",
"Channels": "Kanäle",
"ChapterNameValue": "Kapitel {0}",
"Collections": "Sammlungen",
"DeviceOfflineWithName": "{0} wurde getrennt",
"DeviceOfflineWithName": "{0} hat die Verbindung getrennt",
"DeviceOnlineWithName": "{0} ist verbunden",
"FailedLoginAttemptWithUserName": "Fehlgeschlagener Anmeldeversuch von {0}",
"Favorites": "Favoriten",
@@ -17,7 +17,7 @@
"Genres": "Genres",
"HeaderAlbumArtists": "Album-Interpreten",
"HeaderCameraUploads": "Kamera-Uploads",
"HeaderContinueWatching": "Weiterschauen",
"HeaderContinueWatching": "Fortsetzen",
"HeaderFavoriteAlbums": "Lieblingsalben",
"HeaderFavoriteArtists": "Lieblings-Interpreten",
"HeaderFavoriteEpisodes": "Lieblingsepisoden",

View File

@@ -10,5 +10,12 @@
"CameraImageUploadedFrom": "Se ha subido una nueva imagen de cámara desde {0}",
"AuthenticationSucceededWithUserName": "{0} autenticado con éxito",
"Application": "Aplicación",
"AppDeviceValues": "App: {0}, Dispositivo: {1}"
"AppDeviceValues": "App: {0}, Dispositivo: {1}",
"HeaderContinueWatching": "Continuar Viendo",
"HeaderCameraUploads": "Subidas de Cámara",
"HeaderAlbumArtists": "Artistas del Álbum",
"Genres": "Géneros",
"Folders": "Carpetas",
"Favorites": "Favoritos",
"FailedLoginAttemptWithUserName": "Intento de inicio de sesión fallido de {0}"
}

View File

@@ -17,31 +17,31 @@
"LabelIpAddressValue": "IP-osoite: {0}",
"ItemRemovedWithName": "{0} poistettiin kirjastosta",
"ItemAddedWithName": "{0} lisättiin kirjastoon",
"Inherit": "Periä",
"Inherit": "Periytyä",
"HomeVideos": "Kotivideot",
"HeaderRecordingGroups": "Äänitysryhmät",
"HeaderRecordingGroups": "Nauhoitusryhmät",
"HeaderNextUp": "Seuraavaksi",
"HeaderFavoriteSongs": "Lempikappaleet",
"HeaderFavoriteShows": "Lempisarjat",
"HeaderFavoriteEpisodes": "Lempijaksot",
"HeaderCameraUploads": "Kamerasta lähetetyt",
"HeaderCameraUploads": "Kameralataukset",
"HeaderFavoriteArtists": "Lempiartistit",
"HeaderFavoriteAlbums": "Lempialbumit",
"HeaderContinueWatching": "Jatka katsomista",
"HeaderAlbumArtists": "Albumin artistit",
"Genres": "Tyylilaji",
"HeaderAlbumArtists": "Albumin esittäjä",
"Genres": "Tyylilajit",
"Folders": "Kansiot",
"Favorites": "Suosikit",
"FailedLoginAttemptWithUserName": "Epäonnistunut kirjautumisyritys kohteesta {0}",
"DeviceOnlineWithName": "{0} on yhdistynyt",
"FailedLoginAttemptWithUserName": "Kirjautuminen epäonnistui kohteesta {0}",
"DeviceOnlineWithName": "{0} on yhdistetty",
"DeviceOfflineWithName": "{0} on katkaissut yhteytensä",
"Collections": "Kokoelmat",
"ChapterNameValue": "Luku: {0}",
"Channels": "Kanavat",
"CameraImageUploadedFrom": "Uusi kamerakuva on lähetetty kohteesta {0}",
"CameraImageUploadedFrom": "Uusi kamerakuva on ladattu {0}",
"Books": "Kirjat",
"AuthenticationSucceededWithUserName": "{0} todennettu onnistuneesti",
"Artists": "Artistit",
"AuthenticationSucceededWithUserName": "{0} todennus onnistui",
"Artists": "Esiintyjät",
"Application": "Sovellus",
"AppDeviceValues": "Sovellus: {0}, Laite: {1}",
"Albums": "Albumit",
@@ -76,21 +76,21 @@
"Shows": "Ohjelmat",
"ServerNameNeedsToBeRestarted": "{0} vaatii uudelleenkäynnistyksen",
"ProviderValue": "Palveluntarjoaja: {0}",
"Plugin": "Laajennus",
"Plugin": "Liitännäinen",
"NotificationOptionVideoPlaybackStopped": "Videon toistaminen pysäytetty",
"NotificationOptionVideoPlayback": "Videon toistaminen aloitettu",
"NotificationOptionUserLockedOut": "Käyttäjä kirjautui ulos",
"NotificationOptionTaskFailed": "Ajastetun tehtävän ongelma",
"NotificationOptionServerRestartRequired": "Palvelimen uudelleenkäynnistys vaaditaan",
"NotificationOptionPluginUpdateInstalled": "Laajennuksen päivitys asennettu",
"NotificationOptionPluginUninstalled": "Laajennus poistettu",
"NotificationOptionPluginInstalled": "Laajennus asennettu",
"NotificationOptionPluginError": "Ongelma laajennuksessa",
"NotificationOptionNewLibraryContent": "Uusi sisältö lisätty",
"NotificationOptionInstallationFailed": "Asennusvirhe",
"NotificationOptionCameraImageUploaded": "Kameran kuva lisätty",
"NotificationOptionAudioPlaybackStopped": "Äänen toistaminen pysäytetty",
"NotificationOptionAudioPlayback": "Äänen toistaminen aloitettu",
"NotificationOptionPluginUpdateInstalled": "Liitännäinen päivitetty",
"NotificationOptionPluginUninstalled": "Liitännäinen poistettu",
"NotificationOptionPluginInstalled": "Liitännäinen asennettu",
"NotificationOptionPluginError": "Ongelma liitännäisessä",
"NotificationOptionNewLibraryContent": "Uutta sisältöä lisätty",
"NotificationOptionInstallationFailed": "Asennus epäonnistui",
"NotificationOptionCameraImageUploaded": "Kuva ladattu kamerasta",
"NotificationOptionAudioPlaybackStopped": "Audion toisto pysäytetty",
"NotificationOptionAudioPlayback": "Audion toisto aloitettu",
"NotificationOptionApplicationUpdateInstalled": "Ohjelmistopäivitys asennettu",
"NotificationOptionApplicationUpdateAvailable": "Ohjelmistopäivitys saatavilla"
}

View File

@@ -2,33 +2,33 @@
"Albums": "אלבומים",
"AppDeviceValues": "יישום: {0}, מכשיר: {1}",
"Application": "אפליקציה",
"Artists": "אמנים",
"AuthenticationSucceededWithUserName": "{0} זוהה בהצלחה",
"Artists": ומנים",
"AuthenticationSucceededWithUserName": "{0} אומת בהצלחה",
"Books": "ספרים",
"CameraImageUploadedFrom": "תמונה חדשה הועלתה מ{0}",
"CameraImageUploadedFrom": "תמונת מצלמה חדשה הועלתה מ {0}",
"Channels": "ערוצים",
"ChapterNameValue": "פרק {0}",
"Collections": "קולקציות",
"Collections": "אוספים",
"DeviceOfflineWithName": "{0} התנתק",
"DeviceOnlineWithName": "{0} מחובר",
"FailedLoginAttemptWithUserName": "ניסיון כניסה שגוי מ{0}",
"Favorites": "אהובים",
"Favorites": "מועדפים",
"Folders": "תיקיות",
"Genres": "ז'אנרים",
"HeaderAlbumArtists": "אמני האלבום",
"HeaderCameraUploads": "העלאות ממצלמה",
"HeaderContinueWatching": "המשך לצפות",
"HeaderFavoriteAlbums": "אלבומים שאהבתי",
"HeaderFavoriteArtists": "אמנים שאהבתי",
"HeaderFavoriteEpisodes": "פרקים אהובים",
"HeaderFavoriteShows": "תוכניות אהובות",
"HeaderFavoriteSongs": "שירים שאהבתי",
"HeaderLiveTV": "טלוויזיה בשידור חי",
"HeaderFavoriteArtists": "אמנים מועדפים",
"HeaderFavoriteEpisodes": "פרקים מועדפים",
"HeaderFavoriteShows": "סדרות מועדפות",
"HeaderFavoriteSongs": "שירים מועדפים",
"HeaderLiveTV": "שידורים חיים",
"HeaderNextUp": "הבא",
"HeaderRecordingGroups": "קבוצות הקלטה",
"HomeVideos": "סרטונים בייתים",
"Inherit": "הורש",
"ItemAddedWithName": "{0} was added to the library",
"ItemAddedWithName": "{0} הוסף לספרייה",
"ItemRemovedWithName": "{0} נמחק מהספרייה",
"LabelIpAddressValue": "Ip כתובת: {0}",
"LabelRunningTimeValue": "משך צפייה: {0}",
@@ -36,15 +36,15 @@
"MessageApplicationUpdated": "שרת הJellyfin עודכן",
"MessageApplicationUpdatedTo": "שרת הJellyfin עודכן לגרסא {0}",
"MessageNamedServerConfigurationUpdatedWithValue": "הגדרת השרת {0} שונתה",
"MessageServerConfigurationUpdated": "Server configuration has been updated",
"MessageServerConfigurationUpdated": "תצורת השרת עודכנה",
"MixedContent": "תוכן מעורב",
"Movies": "סרטים",
"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.",
"MusicVideos": "קליפים",
"NameInstallFailed": "התקנת {0} נכשלה",
"NameSeasonNumber": "עונה {0}",
"NameSeasonUnknown": "עונה לא ידועה",
"NewVersionIsAvailable": "גרסה חדשה של שרת Jellyfin זמינה להורדה.",
"NotificationOptionApplicationUpdateAvailable": "Application update available",
"NotificationOptionApplicationUpdateInstalled": "Application update installed",
"NotificationOptionAudioPlayback": "Audio playback started",
@@ -53,10 +53,10 @@
"NotificationOptionInstallationFailed": "התקנה נכשלה",
"NotificationOptionNewLibraryContent": "New content added",
"NotificationOptionPluginError": "Plugin failure",
"NotificationOptionPluginInstalled": "Plugin installed",
"NotificationOptionPluginUninstalled": "Plugin uninstalled",
"NotificationOptionPluginUpdateInstalled": "Plugin update installed",
"NotificationOptionServerRestartRequired": "Server restart required",
"NotificationOptionPluginInstalled": "התוסף הותקן",
"NotificationOptionPluginUninstalled": "התוסף הוסר",
"NotificationOptionPluginUpdateInstalled": "העדכון לתוסף הותקן",
"NotificationOptionServerRestartRequired": "יש לאתחל את השרת",
"NotificationOptionTaskFailed": "Scheduled task failure",
"NotificationOptionUserLockedOut": "User locked out",
"NotificationOptionVideoPlayback": "Video playback started",
@@ -71,26 +71,26 @@
"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.",
"Shows": "סדרות",
"Songs": "שירים",
"StartupEmbyServerIsLoading": "שרת Jellyfin בהליכי טעינה. אנא נסה שנית בעוד זמן קצר.",
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
"SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}",
"SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
"Sync": "סנכרן",
"System": "System",
"TvShows": "TV Shows",
"TvShows": "סדרות טלוויזיה",
"User": "User",
"UserCreatedWithName": "User {0} has been created",
"UserDeletedWithName": "User {0} has been deleted",
"UserDownloadingItemWithValues": "{0} is downloading {1}",
"UserCreatedWithName": "המשתמש {0} נוצר",
"UserDeletedWithName": "המשתמש {0} הוסר",
"UserDownloadingItemWithValues": "{0} מוריד את {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}",
"UserStartedPlayingItemWithValues": "{0} מנגן את {1} על {2}",
"UserStoppedPlayingItemWithValues": "{0} סיים לנגן את {1} על {2}",
"ValueHasBeenAddedToLibrary": "{0} has been added to your media library",
"ValueSpecialEpisodeName": "מיוחד- {0}",
"VersionNumber": "Version {0}"

View File

@@ -11,7 +11,7 @@
"Collections": "Gyűjtemények",
"DeviceOfflineWithName": "{0} kijelentkezett",
"DeviceOnlineWithName": "{0} belépett",
"FailedLoginAttemptWithUserName": "Sikertelen bejelentkezési kísérlet {0}",
"FailedLoginAttemptWithUserName": "Sikertelen bejelentkezési kísérlet tőle: {0}",
"Favorites": "Kedvencek",
"Folders": "Könyvtárak",
"Genres": "Műfajok",
@@ -27,7 +27,7 @@
"HeaderNextUp": "Következik",
"HeaderRecordingGroups": "Felvételi csoportok",
"HomeVideos": "Házi videók",
"Inherit": "Öröklés",
"Inherit": "Örökölt",
"ItemAddedWithName": "{0} hozzáadva a könyvtárhoz",
"ItemRemovedWithName": "{0} eltávolítva a könyvtárból",
"LabelIpAddressValue": "IP cím: {0}",
@@ -73,7 +73,7 @@
"ServerNameNeedsToBeRestarted": "{0}-t újra kell indítani",
"Shows": "Műsorok",
"Songs": "Dalok",
"StartupEmbyServerIsLoading": "A Jellyfin Szerver betöltődik. Kérlek próbáld újra később.",
"StartupEmbyServerIsLoading": "A Jellyfin Szerver betöltődik. Kérlek, próbáld újra hamarosan.",
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
"SubtitleDownloadFailureFromForItem": "Nem sikerült a felirat letöltése innen: {0} ehhez: {1}",
"SubtitlesDownloadedForItem": "Letöltött feliratok a következőhöz: {0}",
@@ -86,11 +86,11 @@
"UserDownloadingItemWithValues": "{0} letölti {1}",
"UserLockedOutWithName": "{0} felhasználó zárolva van",
"UserOfflineFromDevice": "{0} kijelentkezett innen: {1}",
"UserOnlineFromDevice": "{0} online itt: {1}",
"UserOnlineFromDevice": "{0} online innen: {1}",
"UserPasswordChangedWithName": "Jelszó megváltozott a következő felhasználó számára: {0}",
"UserPolicyUpdatedWithName": "A felhasználói házirend frissítve lett neki: {0}",
"UserStartedPlayingItemWithValues": "{0} elkezdte játszani a következőt: {1} itt: {2}",
"UserStoppedPlayingItemWithValues": "{0} befejezte a következőt: {1} itt: {2}",
"UserStoppedPlayingItemWithValues": "{0} befejezte {1} lejátászását itt: {2}",
"ValueHasBeenAddedToLibrary": "{0} hozzáadva a médiatárhoz",
"ValueSpecialEpisodeName": "Special - {0}",
"VersionNumber": "Verzió: {0}"

View File

@@ -91,5 +91,6 @@
"NotificationOptionVideoPlayback": "Pemutaran video dimulai",
"NotificationOptionAudioPlaybackStopped": "Pemutaran audio berhenti",
"NotificationOptionAudioPlayback": "Pemutaran audio dimulai",
"MixedContent": "Konten campur"
"MixedContent": "Konten campur",
"PluginUninstalledWithName": "{0} telah dihapus"
}

View File

@@ -5,7 +5,7 @@
"Artists": "Artisti",
"AuthenticationSucceededWithUserName": "{0} autenticato con successo",
"Books": "Libri",
"CameraImageUploadedFrom": "È stata caricata una nuova immagine della fotocamera {0}",
"CameraImageUploadedFrom": "È stata caricata una nuova immagine della fotocamera da {0}",
"Channels": "Canali",
"ChapterNameValue": "Capitolo {0}",
"Collections": "Collezioni",
@@ -18,7 +18,7 @@
"HeaderAlbumArtists": "Artisti dell' Album",
"HeaderCameraUploads": "Caricamenti Fotocamera",
"HeaderContinueWatching": "Continua a guardare",
"HeaderFavoriteAlbums": "Album preferiti",
"HeaderFavoriteAlbums": "Album Preferiti",
"HeaderFavoriteArtists": "Artisti Preferiti",
"HeaderFavoriteEpisodes": "Episodi Preferiti",
"HeaderFavoriteShows": "Serie TV Preferite",

View File

@@ -0,0 +1,96 @@
{
"ServerNameNeedsToBeRestarted": "{0} ir vajadzīgs restarts",
"NotificationOptionTaskFailed": "Plānota uzdevuma kļūme",
"HeaderRecordingGroups": "Ierakstu Grupas",
"UserPolicyUpdatedWithName": "Lietotāju politika atjaunota priekš {0}",
"SubtitleDownloadFailureFromForItem": "Subtitru lejupielāde no {0} priekš {1} neizdevās",
"NotificationOptionVideoPlaybackStopped": "Video atskaņošana apturēta",
"NotificationOptionVideoPlayback": "Video atskaņošana sākta",
"NotificationOptionInstallationFailed": "Instalācija neizdevās",
"AuthenticationSucceededWithUserName": "{0} veiksmīgi autentificējies",
"ValueSpecialEpisodeName": "Speciālais - {0}",
"ScheduledTaskStartedWithName": "{0} iesākts",
"ScheduledTaskFailedWithName": "{0} neizdevās",
"Photos": "Attēli",
"NotificationOptionUserLockedOut": "Lietotājs bloķēts",
"LabelRunningTimeValue": "Garums: {0}",
"Inherit": "Mantot",
"AppDeviceValues": "Lietotne:{0}, Ierīce:{1}",
"VersionNumber": "Versija {0}",
"ValueHasBeenAddedToLibrary": "{0} ir ticis pievienots tavai multvides bibliotēkai",
"UserStoppedPlayingItemWithValues": "{0} ir beidzis atskaņot {1} uz {2}",
"UserStartedPlayingItemWithValues": "{0} atskaņo {1} uz {2}",
"UserPasswordChangedWithName": "Parole nomainīta lietotājam {0}",
"UserOnlineFromDevice": "{0} ir tiešsaistē no {1}",
"UserOfflineFromDevice": "{0} ir atvienojies no {1}",
"UserLockedOutWithName": "Lietotājs {0} ir ticis bloķēts",
"UserDownloadingItemWithValues": "{0} lejupielādē {1}",
"UserDeletedWithName": "Lietotājs {0} ir izdzēsts",
"UserCreatedWithName": "Lietotājs {0} ir ticis izveidots",
"User": "Lietotājs",
"TvShows": "TV Raidījumi",
"Sync": "Sinhronizācija",
"System": "Sistēma",
"SubtitlesDownloadedForItem": "Subtitri lejupielādēti priekš {0}",
"StartupEmbyServerIsLoading": "Jellyfin Serveris lādējas. Lūdzu mēģiniet vēlreiz pēc brīža.",
"Songs": "Dziesmas",
"Shows": "Raidījumi",
"PluginUpdatedWithName": "{0} tika atjaunots",
"PluginUninstalledWithName": "{0} tika noņemts",
"PluginInstalledWithName": "{0} tika uzstādīts",
"Plugin": "Paplašinājums",
"Playlists": "Atskaņošanas Saraksti",
"MixedContent": "Jaukts saturs",
"HomeVideos": "Mājas Video",
"HeaderNextUp": "Nākamais",
"ChapterNameValue": "Nodaļa {0}",
"Application": "Lietotne",
"NotificationOptionServerRestartRequired": "Vajadzīgs servera restarts",
"NotificationOptionPluginUpdateInstalled": "Paplašinājuma atjauninājums uzstādīts",
"NotificationOptionPluginUninstalled": "Paplašinājums noņemts",
"NotificationOptionPluginInstalled": "Paplašinājums uzstādīts",
"NotificationOptionPluginError": "Paplašinājuma kļūda",
"NotificationOptionNewLibraryContent": "Jauns saturs pievienots",
"NotificationOptionCameraImageUploaded": "Kameras attēls augšupielādēts",
"NotificationOptionAudioPlaybackStopped": "Audio atskaņošana apturēta",
"NotificationOptionAudioPlayback": "Audio atskaņošana sākta",
"NotificationOptionApplicationUpdateInstalled": "Lietotnes atjauninājums uzstādīts",
"NotificationOptionApplicationUpdateAvailable": "Lietotnes atjauninājums pieejams",
"NewVersionIsAvailable": "Lejupielādei ir pieejama jauna Jellyfin Server versija.",
"NameSeasonUnknown": "Nezināma Sezona",
"NameSeasonNumber": "Sezona {0}",
"NameInstallFailed": "{0} instalācija neizdevās",
"MusicVideos": "Mūzikas video",
"Music": "Mūzika",
"Movies": "Filmas",
"MessageServerConfigurationUpdated": "Servera konfigurācija ir tikusi atjaunota",
"MessageNamedServerConfigurationUpdatedWithValue": "Servera konfigurācijas sadaļa {0} ir tikusi atjaunota",
"MessageApplicationUpdatedTo": "Jellyfin Server ir ticis atjaunots uz {0}",
"MessageApplicationUpdated": "Jellyfin Server ir ticis atjaunots",
"Latest": "Jaunākais",
"LabelIpAddressValue": "IP adrese: {0}",
"ItemRemovedWithName": "{0} tika noņemts no bibliotēkas",
"ItemAddedWithName": "{0} tika pievienots bibliotēkai",
"HeaderLiveTV": "Tiešraides TV",
"HeaderContinueWatching": "Turpināt Skatīšanos",
"HeaderCameraUploads": "Kameras augšupielādes",
"HeaderAlbumArtists": "Albumu Izpildītāji",
"Genres": "Žanri",
"Folders": "Mapes",
"Favorites": "Favorīti",
"FailedLoginAttemptWithUserName": "Neizdevies pieslēgšanās mēģinājums no {0}",
"DeviceOnlineWithName": "{0} ir pievienojies",
"DeviceOfflineWithName": "{0} ir atvienojies",
"Collections": "Kolekcijas",
"Channels": "Kanāli",
"CameraImageUploadedFrom": "Jauns kameras attēls ir ticis augšupielādēts no {0}",
"Books": "Grāmatas",
"Artists": "Izpildītāji",
"Albums": "Albumi",
"ProviderValue": "Provider: {0}",
"HeaderFavoriteSongs": "Dziesmu Favorīti",
"HeaderFavoriteShows": "Raidījumu Favorīti",
"HeaderFavoriteEpisodes": "Episožu Favorīti",
"HeaderFavoriteArtists": "Izpildītāju Favorīti",
"HeaderFavoriteAlbums": "Albumu Favorīti"
}

View File

@@ -0,0 +1,96 @@
{
"ScheduledTaskFailedWithName": "{0} неуспешно",
"ProviderValue": "Провајдер: {0}",
"PluginUpdatedWithName": "{0} беше надоградено",
"PluginUninstalledWithName": "{0} беше успешно деинсталирано",
"PluginInstalledWithName": "{0} беше успешно инсталирано",
"Plugin": "Додатоци",
"Playlists": "Листи",
"Photos": "Слики",
"NotificationOptionVideoPlaybackStopped": "Видео стопирано",
"NotificationOptionVideoPlayback": "Видео пуштено",
"NotificationOptionUserLockedOut": "Корисникот е ослободен",
"NotificationOptionTaskFailed": "Закажани задачи неуспешно",
"NotificationOptionServerRestartRequired": "Задолжително рестартирање на серверот",
"NotificationOptionPluginUpdateInstalled": "Надоградба на Додаток успешна",
"NotificationOptionPluginUninstalled": "Додаток успешно деинсталиран",
"NotificationOptionPluginInstalled": "Додаток успешно инсталиран",
"NotificationOptionPluginError": "Грешка на додаток",
"NotificationOptionNewLibraryContent": "Додадена нова содржина",
"NotificationOptionInstallationFailed": "Неуспешна Инсталација",
"NotificationOptionCameraImageUploaded": "Слика од камера поставена",
"NotificationOptionAudioPlaybackStopped": "Аудио стопирано",
"NotificationOptionAudioPlayback": "Аудио стартувано",
"NotificationOptionApplicationUpdateInstalled": "Надоградбата на Апликацијата е иснталирана",
"NotificationOptionApplicationUpdateAvailable": "Возможна надоградба на Апликацијата",
"NewVersionIsAvailable": "Нова верзија од Jellyfin е возможна за спуштање.",
"NameSeasonUnknown": "Непозната Сезона",
"NameSeasonNumber": "Сезона {0}",
"NameInstallFailed": "{0} неуспешна инсталација",
"MusicVideos": "Музички видеа",
"Music": "Музика",
"Movies": "Филмови",
"MixedContent": "Мешана содржина",
"MessageServerConfigurationUpdated": "Серверската конфигурација беше надградена",
"MessageNamedServerConfigurationUpdatedWithValue": "Секцијата на конфигурација на сервер {0} беше надоградена",
"MessageApplicationUpdatedTo": "Jellyfin беше надограден до {0}",
"MessageApplicationUpdated": "Jellyfin Серверот беше надограден",
"Latest": "Последно",
"LabelRunningTimeValue": "Време на работа: {0}",
"LabelIpAddressValue": "ИП Адреса: {0}",
"ItemRemovedWithName": "{0} е избришано до Библиотеката",
"ItemAddedWithName": "{0} беше додадено во Библиотеката",
"Inherit": "Следно",
"HomeVideos": "Домашни Видеа",
"HeaderRecordingGroups": "Групи на снимање",
"HeaderNextUp": "Следно",
"HeaderLiveTV": "ТВ",
"HeaderFavoriteSongs": "Омилени Песни",
"HeaderFavoriteShows": "Омилени Серии",
"HeaderFavoriteEpisodes": "Омилени Епизоди",
"HeaderFavoriteArtists": "Омилени Изведувачи",
"HeaderFavoriteAlbums": "Омилени Албуми",
"HeaderContinueWatching": "Продолжи со гледање",
"HeaderCameraUploads": "Поставувања од камера",
"HeaderAlbumArtists": "Изведувачи од Албуми",
"Genres": "Жанрови",
"Folders": "Папки",
"Favorites": "Омилени",
"FailedLoginAttemptWithUserName": "Неуспешно поврзување од {0}",
"DeviceOnlineWithName": "{0} е приклучен",
"DeviceOfflineWithName": "{0} се исклучи",
"Collections": "Колекции",
"ChapterNameValue": "Дел {0}",
"Channels": "Канали",
"CameraImageUploadedFrom": "Нова слика од камера беше поставена од {0}",
"Books": "Книги",
"AuthenticationSucceededWithUserName": "{0} успешно поврзан",
"Artists": "Изведувач",
"Application": "Апликација",
"AppDeviceValues": "Аплиакција: {0}, Уред: {1}",
"Albums": "Албуми",
"VersionNumber": "Верзија {0}",
"ValueSpecialEpisodeName": "Специјално - {0}",
"ValueHasBeenAddedToLibrary": "{0} е додадено во твојата библиотека",
"UserStoppedPlayingItemWithValues": "{0} заврши со репродукција {1} во {2}",
"UserStartedPlayingItemWithValues": "{0} пушти {1} на {2}",
"UserPolicyUpdatedWithName": "Полисата на користење беше надоградена за {0}",
"UserPasswordChangedWithName": "Лозинката е сменета за корисникот {0}",
"UserOnlineFromDevice": "{0} е приклучен од {1}",
"UserOfflineFromDevice": "{0} е дисконектиран од {1}",
"UserLockedOutWithName": "Корисникот {0} е заклучен",
"UserDownloadingItemWithValues": "{0} се спушта {1}",
"UserDeletedWithName": "Корисникот {0} е избришан",
"UserCreatedWithName": "Корисникот {0} е креиран",
"User": "Корисник",
"TvShows": "ТВ Серии",
"System": "Систем",
"Sync": "Синхронизација",
"SubtitlesDownloadedForItem": "Спуштање превод за {0}",
"SubtitleDownloadFailureFromForItem": "Преводот неуспешно се спушти од {0} за {1}",
"StartupEmbyServerIsLoading": "Jellyfin Server се пушта. Ве молиме причекајте.",
"Songs": "Песни",
"Shows": "Серии",
"ServerNameNeedsToBeRestarted": "{0} треба да се рестартира",
"ScheduledTaskStartedWithName": "{0} започна"
}

View File

@@ -1,9 +1,9 @@
{
"Albums": "Album-album",
"AppDeviceValues": "App: {0}, Device: {1}",
"AppDeviceValues": "Apl: {0}, Peranti: {1}",
"Application": "Aplikasi",
"Artists": "Artis-artis",
"AuthenticationSucceededWithUserName": "{0} successfully authenticated",
"Artists": "Artis",
"AuthenticationSucceededWithUserName": "{0} berjaya disahkan",
"Books": "Buku-buku",
"CameraImageUploadedFrom": "A new camera image has been uploaded from {0}",
"Channels": "Saluran",
@@ -30,7 +30,7 @@
"Inherit": "Inherit",
"ItemAddedWithName": "{0} was added to the library",
"ItemRemovedWithName": "{0} was removed from the library",
"LabelIpAddressValue": "Ip address: {0}",
"LabelIpAddressValue": "Alamat IP: {0}",
"LabelRunningTimeValue": "Running time: {0}",
"Latest": "Latest",
"MessageApplicationUpdated": "Jellyfin Server has been updated",
@@ -50,7 +50,7 @@
"NotificationOptionAudioPlayback": "Audio playback started",
"NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
"NotificationOptionCameraImageUploaded": "Camera image uploaded",
"NotificationOptionInstallationFailed": "Installation failure",
"NotificationOptionInstallationFailed": "Pemasangan gagal",
"NotificationOptionNewLibraryContent": "New content added",
"NotificationOptionPluginError": "Plugin failure",
"NotificationOptionPluginInstalled": "Plugin installed",

View File

@@ -3,13 +3,13 @@
"AppDeviceValues": "App: {0}, Apparaat: {1}",
"Application": "Applicatie",
"Artists": "Artiesten",
"AuthenticationSucceededWithUserName": "{0} is succesvol geverifieerd",
"AuthenticationSucceededWithUserName": "{0} succesvol geauthenticeerd",
"Books": "Boeken",
"CameraImageUploadedFrom": "Er is een nieuwe foto toegevoegd van {0}",
"Channels": "Kanalen",
"ChapterNameValue": "Hoofdstuk {0}",
"Collections": "Verzamelingen",
"DeviceOfflineWithName": "{0} heeft de verbinding verbroken",
"DeviceOfflineWithName": "Verbinding met {0} is verbroken",
"DeviceOnlineWithName": "{0} is verbonden",
"FailedLoginAttemptWithUserName": "Mislukte aanmeld poging van {0}",
"Favorites": "Favorieten",

View File

@@ -1 +1,40 @@
{}
{
"MessageServerConfigurationUpdated": "Tenar konfigurasjonen har blitt oppdatert",
"MessageNamedServerConfigurationUpdatedWithValue": "Tenar konfigurasjon seksjon {0} har blitt oppdatert",
"MessageApplicationUpdatedTo": "Jellyfin Tenaren har blitt oppdatert til {0}",
"MessageApplicationUpdated": "Jellyfin Tenaren har blitt oppdatert",
"Latest": "Nyaste",
"LabelRunningTimeValue": "Speletid: {0}",
"LabelIpAddressValue": "IP adresse: {0}",
"ItemRemovedWithName": "{0} vart fjerna frå biblioteket",
"ItemAddedWithName": "{0} vart lagt til i biblioteket",
"Inherit": "Arv",
"HomeVideos": "Heime Videoar",
"HeaderRecordingGroups": "Innspelingsgrupper",
"HeaderNextUp": "Neste",
"HeaderLiveTV": "Direkte TV",
"HeaderFavoriteSongs": "Favoritt Songar",
"HeaderFavoriteShows": "Favoritt Seriar",
"HeaderFavoriteEpisodes": "Favoritt Episodar",
"HeaderFavoriteArtists": "Favoritt Artistar",
"HeaderFavoriteAlbums": "Favoritt Album",
"HeaderContinueWatching": "Fortsett å sjå",
"HeaderCameraUploads": "Kamera Opplastingar",
"HeaderAlbumArtists": "Album Artist",
"Genres": "Sjangrar",
"Folders": "Mapper",
"Favorites": "Favorittar",
"FailedLoginAttemptWithUserName": "Mislukka påloggingsforsøk frå {0}",
"DeviceOnlineWithName": "{0} er tilkopla",
"DeviceOfflineWithName": "{0} har kopla frå",
"Collections": "Samlingar",
"ChapterNameValue": "Kapittel {0}",
"Channels": "Kanalar",
"CameraImageUploadedFrom": "Eit nytt kamera bilete har blitt lasta opp frå {0}",
"Books": "Bøker",
"AuthenticationSucceededWithUserName": "{0} Har logga inn",
"Artists": "Artistar",
"Application": "Program",
"AppDeviceValues": "App: {0}, Einheit: {1}",
"Albums": "Album"
}

View File

@@ -1,5 +1,5 @@
{
"HeaderLiveTV": "TV ao Vivo",
"HeaderLiveTV": "TV em Directo",
"Collections": "Colecções",
"Books": "Livros",
"Artists": "Artistas",
@@ -10,13 +10,13 @@
"HeaderFavoriteAlbums": "Álbuns Favoritos",
"HeaderFavoriteEpisodes": "Episódios Favoritos",
"HeaderFavoriteShows": "Séries Favoritas",
"HeaderContinueWatching": "Continuar a Ver",
"HeaderContinueWatching": "Continuar a Assistir",
"HeaderAlbumArtists": "Artistas do Álbum",
"Genres": "Géneros",
"Folders": "Pastas",
"Folders": "Directórios",
"Favorites": "Favoritos",
"Channels": "Canais",
"UserDownloadingItemWithValues": "{0} está a transferir {1}",
"UserDownloadingItemWithValues": "{0} está a ser transferido {1}",
"VersionNumber": "Versão {0}",
"ValueHasBeenAddedToLibrary": "{0} foi adicionado à sua biblioteca multimédia",
"UserStoppedPlayingItemWithValues": "{0} terminou a reprodução de {1} em {2}",
@@ -24,12 +24,12 @@
"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",
"UserOfflineFromDevice": "{0} desconectou-se a partir de {1}",
"UserLockedOutWithName": "O utilizador {0} foi bloqueado",
"UserDeletedWithName": "O utilizador {0} foi removido",
"UserCreatedWithName": "O utilizador {0} foi criado",
"User": "Utilizador",
"TvShows": "Programas",
"TvShows": "Séries",
"System": "Sistema",
"SubtitlesDownloadedForItem": "Legendas transferidas para {0}",
"SubtitleDownloadFailureFromForItem": "Falha na transferência de legendas de {0} para {1}",
@@ -38,22 +38,22 @@
"ScheduledTaskStartedWithName": "{0} iniciou",
"ScheduledTaskFailedWithName": "{0} falhou",
"ProviderValue": "Fornecedor: {0}",
"PluginUpdatedWithName": "{0} foi actualizado",
"PluginUpdatedWithName": "{0} foi atualizado",
"PluginUninstalledWithName": "{0} foi desinstalado",
"PluginInstalledWithName": "{0} foi instalado",
"Plugin": "Extensão",
"Plugin": "Plugin",
"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",
"NotificationOptionPluginUpdateInstalled": "Plugin actualizado",
"NotificationOptionPluginUninstalled": "Plugin desinstalado",
"NotificationOptionPluginInstalled": "Plugin instalado",
"NotificationOptionPluginError": "Falha no plugin",
"NotificationOptionNewLibraryContent": "Novo conteúdo adicionado",
"NotificationOptionInstallationFailed": "Falha de instalação",
"NotificationOptionCameraImageUploaded": "Imagem da câmara enviada",
"NotificationOptionCameraImageUploaded": "Imagem de câmara enviada",
"NotificationOptionAudioPlaybackStopped": "Reprodução Parada",
"NotificationOptionAudioPlayback": "Reprodução Iniciada",
"NotificationOptionApplicationUpdateInstalled": "A actualização da aplicação foi instalada",
@@ -66,30 +66,30 @@
"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}",
"MessageNamedServerConfigurationUpdatedWithValue": "As configurações do servidor na secção {0} foram atualizadas",
"MessageApplicationUpdatedTo": "O servidor Jellyfin foi atualizado para a versão {0}",
"MessageApplicationUpdated": "O servidor Jellyfin foi actualizado",
"Latest": "Mais Recente",
"LabelRunningTimeValue": "Duração: {0}",
"LabelIpAddressValue": "Endereço IP: {0}",
"LabelIpAddressValue": "Endereço de 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}",
"ValueSpecialEpisodeName": "Episódio 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",
"HeaderCameraUploads": "Carregamentos a partir da câmara",
"FailedLoginAttemptWithUserName": "Tentativa de ligação falhada a partir de {0}",
"DeviceOnlineWithName": "{0} está connectado",
"DeviceOfflineWithName": "{0} desconectou-se",
"ChapterNameValue": "Capítulo {0}",
"CameraImageUploadedFrom": "Uma nova imagem de câmara foi enviada a partir de {0}",
"CameraImageUploadedFrom": "Uma nova imagem da câmara foi enviada a partir de {0}",
"AuthenticationSucceededWithUserName": "{0} autenticado com sucesso",
"Application": "Aplicação",
"AppDeviceValues": "Aplicação {0}, Dispositivo: {1}"

View File

@@ -1,7 +1,7 @@
{
"Albums": "Album",
"AppDeviceValues": "App: {0}, Enhet: {1}",
"Application": "App",
"AppDeviceValues": "Applikation: {0}, Enhet: {1}",
"Application": "Applikation",
"Artists": "Artister",
"AuthenticationSucceededWithUserName": "{0} har autentiserats",
"Books": "Böcker",
@@ -16,15 +16,15 @@
"Folders": "Mappar",
"Genres": "Genrer",
"HeaderAlbumArtists": "Albumartister",
"HeaderCameraUploads": "Kamera Uppladdningar",
"HeaderContinueWatching": "Fortsätt kolla",
"HeaderCameraUploads": "Kamerauppladdningar",
"HeaderContinueWatching": "Fortsätt kolla",
"HeaderFavoriteAlbums": "Favoritalbum",
"HeaderFavoriteArtists": "Favoritartister",
"HeaderFavoriteEpisodes": "Favoritavsnitt",
"HeaderFavoriteShows": "Favoritserier",
"HeaderFavoriteSongs": "Favoritlåtar",
"HeaderLiveTV": "Live-TV",
"HeaderNextUp": "Nästa på tur",
"HeaderNextUp": "Nästa",
"HeaderRecordingGroups": "Inspelningsgrupper",
"HomeVideos": "Hemvideor",
"Inherit": "Ärv",
@@ -34,9 +34,9 @@
"LabelRunningTimeValue": "Speltid: {0}",
"Latest": "Senaste",
"MessageApplicationUpdated": "Jellyfin Server har uppdaterats",
"MessageApplicationUpdatedTo": "Jellyfin Server har uppgraderats till {0}",
"MessageApplicationUpdatedTo": "Jellyfin Server har uppdaterats till {0}",
"MessageNamedServerConfigurationUpdatedWithValue": "Serverinställningarna {0} har uppdaterats",
"MessageServerConfigurationUpdated": "Server konfigurationen har uppdaterats",
"MessageServerConfigurationUpdated": "Serverkonfigurationen har uppdaterats",
"MixedContent": "Blandat innehåll",
"Movies": "Filmer",
"Music": "Musik",
@@ -44,11 +44,11 @@
"NameInstallFailed": "{0} installationen misslyckades",
"NameSeasonNumber": "Säsong {0}",
"NameSeasonUnknown": "Okänd säsong",
"NewVersionIsAvailable": "En ny version av Jellyfin Server är klar för nedladdning.",
"NewVersionIsAvailable": "En ny version av Jellyfin Server är tillgänglig att hämta.",
"NotificationOptionApplicationUpdateAvailable": "Ny programversion tillgänglig",
"NotificationOptionApplicationUpdateInstalled": "Programuppdatering installerad",
"NotificationOptionAudioPlayback": "Ljuduppspelning har påbörjats",
"NotificationOptionAudioPlaybackStopped": "Ljuduppspelning stoppad",
"NotificationOptionAudioPlaybackStopped": "Ljuduppspelning stoppades",
"NotificationOptionCameraImageUploaded": "Kamerabild har laddats upp",
"NotificationOptionInstallationFailed": "Fel vid installation",
"NotificationOptionNewLibraryContent": "Nytt innehåll har lagts till",
@@ -60,7 +60,7 @@
"NotificationOptionTaskFailed": "Schemalagd aktivitet har misslyckats",
"NotificationOptionUserLockedOut": "Användare har låsts ut",
"NotificationOptionVideoPlayback": "Videouppspelning har påbörjats",
"NotificationOptionVideoPlaybackStopped": "Videouppspelning stoppad",
"NotificationOptionVideoPlaybackStopped": "Videouppspelning stoppades",
"Photos": "Bilder",
"Playlists": "Spellistor",
"Plugin": "Tillägg",
@@ -69,13 +69,13 @@
"PluginUpdatedWithName": "{0} uppdaterades",
"ProviderValue": "Källa: {0}",
"ScheduledTaskFailedWithName": "{0} misslyckades",
"ScheduledTaskStartedWithName": "{0} startad",
"ScheduledTaskStartedWithName": "{0} startades",
"ServerNameNeedsToBeRestarted": "{0} behöver startas om",
"Shows": "Serier",
"Songs": "Låtar",
"StartupEmbyServerIsLoading": "Jellyfin server arbetar. Pröva igen inom kort.",
"StartupEmbyServerIsLoading": "Jellyfin Server arbetar. Pröva igen snart.",
"SubtitleDownloadFailureForItem": "Nerladdning av undertexter för {0} misslyckades",
"SubtitleDownloadFailureFromForItem": "Undertexter misslyckades att ladda ner {0} för {1}",
"SubtitleDownloadFailureFromForItem": "Undertexter kunde inte laddas ner från {0} för {1}",
"SubtitlesDownloadedForItem": "Undertexter har laddats ner till {0}",
"Sync": "Synk",
"System": "System",
@@ -89,9 +89,9 @@
"UserOnlineFromDevice": "{0} är uppkopplad från {1}",
"UserPasswordChangedWithName": "Lösenordet för {0} har ändrats",
"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} har blivit tillagd till ditt mediabibliotek",
"UserStartedPlayingItemWithValues": "{0} spelar upp {1} på {2}",
"UserStoppedPlayingItemWithValues": "{0} har avslutat uppspelningen av {1} på {2}",
"ValueHasBeenAddedToLibrary": "{0} har lagts till i ditt mediebibliotek",
"ValueSpecialEpisodeName": "Specialavsnitt - {0}",
"VersionNumber": "Version {0}"
}

View File

@@ -17,14 +17,14 @@
"Genres": "风格",
"HeaderAlbumArtists": "专辑作家",
"HeaderCameraUploads": "相机上传",
"HeaderContinueWatching": "继续观",
"HeaderContinueWatching": "继续观",
"HeaderFavoriteAlbums": "收藏的专辑",
"HeaderFavoriteArtists": "最爱的艺术家",
"HeaderFavoriteEpisodes": "最爱的剧集",
"HeaderFavoriteShows": "最爱的节目",
"HeaderFavoriteSongs": "最爱的歌曲",
"HeaderLiveTV": "电视直播",
"HeaderNextUp": "下一步",
"HeaderNextUp": "接下来",
"HeaderRecordingGroups": "录制组",
"HomeVideos": "家庭视频",
"Inherit": "继承",

View File

@@ -33,14 +33,14 @@ namespace Emby.Server.Implementations.Playlists
ILibraryManager libraryManager,
IFileSystem fileSystem,
ILibraryMonitor iLibraryMonitor,
ILoggerFactory loggerFactory,
ILogger<PlaylistManager> logger,
IUserManager userManager,
IProviderManager providerManager)
{
_libraryManager = libraryManager;
_fileSystem = fileSystem;
_iLibraryMonitor = iLibraryMonitor;
_logger = loggerFactory.CreateLogger(nameof(PlaylistManager));
_logger = logger;
_userManager = userManager;
_providerManager = providerManager;
}

View File

@@ -29,7 +29,10 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
/// <summary>
/// Initializes a new instance of the <see cref="DeleteCacheFileTask" /> class.
/// </summary>
public DeleteCacheFileTask(IApplicationPaths appPaths, ILogger logger, IFileSystem fileSystem)
public DeleteCacheFileTask(
IApplicationPaths appPaths,
ILogger<DeleteCacheFileTask> logger,
IFileSystem fileSystem)
{
ApplicationPaths = appPaths;
_logger = logger;

View File

@@ -23,7 +23,10 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
/// <summary>
/// Initializes a new instance of the <see cref="DeleteTranscodeFileTask" /> class.
/// </summary>
public DeleteTranscodeFileTask(ILogger logger, IFileSystem fileSystem, IConfigurationManager configurationManager)
public DeleteTranscodeFileTask(
ILogger<DeleteTranscodeFileTask> logger,
IFileSystem fileSystem,
IConfigurationManager configurationManager)
{
_logger = logger;
_fileSystem = fileSystem;

View File

@@ -23,7 +23,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
private readonly IInstallationManager _installationManager;
public PluginUpdateTask(ILogger logger, IInstallationManager installationManager)
public PluginUpdateTask(ILogger<PluginUpdateTask> logger, IInstallationManager installationManager)
{
_logger = logger;
_installationManager = installationManager;

View File

@@ -21,15 +21,14 @@ namespace Emby.Server.Implementations.SocketSharp
private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource();
private CancellationToken _disposeCancellationToken;
public WebSocketSharpListener(
ILogger logger)
public WebSocketSharpListener(ILogger<WebSocketSharpListener> logger)
{
_logger = logger;
_disposeCancellationToken = _disposeCancellationTokenSource.Token;
}
public Func<Exception, IRequest, bool, bool, Task> ErrorHandler { get; set; }
public Func<IHttpRequest, string, string, string, CancellationToken, Task> RequestHandler { get; set; }
public Action<WebSocketConnectEventArgs> WebSocketConnected { get; set; }

View File

@@ -1,99 +0,0 @@
using System.Collections.Generic;
using System.Text;
using MediaBrowser.Controller.Sorting;
namespace Emby.Server.Implementations.Sorting
{
public class AlphanumComparator : IComparer<string>
{
public static int CompareValues(string s1, string s2)
{
if (s1 == null || s2 == null)
{
return 0;
}
int thisMarker = 0, thisNumericChunk = 0;
int thatMarker = 0, thatNumericChunk = 0;
while ((thisMarker < s1.Length) || (thatMarker < s2.Length))
{
if (thisMarker >= s1.Length)
{
return -1;
}
else if (thatMarker >= s2.Length)
{
return 1;
}
char thisCh = s1[thisMarker];
char thatCh = s2[thatMarker];
var thisChunk = new StringBuilder();
var thatChunk = new StringBuilder();
while ((thisMarker < s1.Length) && (thisChunk.Length == 0 || SortHelper.InChunk(thisCh, thisChunk[0])))
{
thisChunk.Append(thisCh);
thisMarker++;
if (thisMarker < s1.Length)
{
thisCh = s1[thisMarker];
}
}
while ((thatMarker < s2.Length) && (thatChunk.Length == 0 || SortHelper.InChunk(thatCh, thatChunk[0])))
{
thatChunk.Append(thatCh);
thatMarker++;
if (thatMarker < s2.Length)
{
thatCh = s2[thatMarker];
}
}
int result = 0;
// If both chunks contain numeric characters, sort them numerically
if (char.IsDigit(thisChunk[0]) && char.IsDigit(thatChunk[0]))
{
if (!int.TryParse(thisChunk.ToString(), out thisNumericChunk))
{
return 0;
}
if (!int.TryParse(thatChunk.ToString(), out thatNumericChunk))
{
return 0;
}
if (thisNumericChunk < thatNumericChunk)
{
result = -1;
}
if (thisNumericChunk > thatNumericChunk)
{
result = 1;
}
}
else
{
result = thisChunk.ToString().CompareTo(thatChunk.ToString());
}
if (result != 0)
{
return result;
}
}
return 0;
}
public int Compare(string x, string y)
{
return CompareValues(x, y);
}
}
}