diff options
Diffstat (limited to 'Emby.Server.Implementations')
132 files changed, 644 insertions, 1198 deletions
diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs index efe8f98ec..739f68767 100644 --- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs +++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading.Tasks; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; @@ -58,7 +59,7 @@ namespace Emby.Server.Implementations.Activity _deviceManager = deviceManager; } - public void Run() + public Task RunAsync() { _taskManager.TaskCompleted += _taskManager_TaskCompleted; @@ -90,6 +91,8 @@ namespace Emby.Server.Implementations.Activity _deviceManager.CameraImageUploaded += _deviceManager_CameraImageUploaded; _appHost.ApplicationUpdated += _appHost_ApplicationUpdated; + + return Task.CompletedTask; } void _deviceManager_CameraImageUploaded(object sender, GenericEventArgs<CameraImageUploadInfo> e) @@ -207,10 +210,6 @@ namespace Emby.Server.Implementations.Activity { return NotificationType.AudioPlayback.ToString(); } - if (string.Equals(mediaType, MediaType.Game, StringComparison.OrdinalIgnoreCase)) - { - return NotificationType.GamePlayback.ToString(); - } if (string.Equals(mediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase)) { return NotificationType.VideoPlayback.ToString(); @@ -225,10 +224,6 @@ namespace Emby.Server.Implementations.Activity { return NotificationType.AudioPlaybackStopped.ToString(); } - if (string.Equals(mediaType, MediaType.Game, StringComparison.OrdinalIgnoreCase)) - { - return NotificationType.GamePlaybackStopped.ToString(); - } if (string.Equals(mediaType, MediaType.Video, StringComparison.OrdinalIgnoreCase)) { return NotificationType.VideoPlaybackStopped.ToString(); diff --git a/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs b/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs index e4a2cd9df..701c04f9e 100644 --- a/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs +++ b/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs @@ -16,12 +16,14 @@ namespace Emby.Server.Implementations.AppBase string programDataPath, string appFolderPath, string logDirectoryPath = null, - string configurationDirectoryPath = null) + string configurationDirectoryPath = null, + string cacheDirectoryPath = null) { ProgramDataPath = programDataPath; ProgramSystemPath = appFolderPath; LogDirectoryPath = logDirectoryPath; ConfigurationDirectoryPath = configurationDirectoryPath; + CachePath = cacheDirectoryPath; } public string ProgramDataPath { get; private set; } diff --git a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs index 90b43bc59..5feac1adf 100644 --- a/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs +++ b/Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs @@ -171,16 +171,29 @@ namespace Emby.Server.Implementations.AppBase private void UpdateCachePath() { string cachePath; - + // If the configuration file has no entry (i.e. not set in UI) if (string.IsNullOrWhiteSpace(CommonConfiguration.CachePath)) { - cachePath = null; + // If the current live configuration has no entry (i.e. not set on CLI/envvars, during startup) + if (string.IsNullOrWhiteSpace(((BaseApplicationPaths)CommonApplicationPaths).CachePath)) + { + // Set cachePath to a default value under ProgramDataPath + cachePath = Path.Combine(((BaseApplicationPaths)CommonApplicationPaths).ProgramDataPath, "cache"); + } + else + { + // Set cachePath to the existing live value; will require restart if UI value is removed (but not replaced) + // TODO: Figure out how to re-grab this from the CLI/envvars while running + cachePath = ((BaseApplicationPaths)CommonApplicationPaths).CachePath; + } } else { - cachePath = Path.Combine(CommonConfiguration.CachePath, "cache"); + // Set cachePath to the new UI-set value + cachePath = CommonConfiguration.CachePath; } + Logger.LogInformation("Setting cache path to " + cachePath); ((BaseApplicationPaths)CommonApplicationPaths).CachePath = cachePath; } @@ -217,7 +230,7 @@ namespace Emby.Server.Implementations.AppBase private string GetConfigurationFile(string key) { - return Path.Combine(CommonApplicationPaths.ConfigurationDirectoryPath, key.ToLower() + ".xml"); + return Path.Combine(CommonApplicationPaths.ConfigurationDirectoryPath, key.ToLowerInvariant() + ".xml"); } public object GetConfiguration(string key) diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs index 31dad48be..bb475eb2c 100644 --- a/Emby.Server.Implementations/ApplicationHost.cs +++ b/Emby.Server.Implementations/ApplicationHost.cs @@ -12,7 +12,6 @@ using System.Security.Cryptography.X509Certificates; using System.Text; using System.Threading; using System.Threading.Tasks; -using Emby.Common.Implementations.Serialization; using Emby.Dlna; using Emby.Dlna.Main; using Emby.Dlna.Ssdp; @@ -43,7 +42,6 @@ using Emby.Server.Implementations.ScheduledTasks; using Emby.Server.Implementations.Security; using Emby.Server.Implementations.Serialization; using Emby.Server.Implementations.Session; -using Emby.Server.Implementations.Threading; using Emby.Server.Implementations.TV; using Emby.Server.Implementations.Updates; using Emby.Server.Implementations.Xml; @@ -99,7 +97,6 @@ using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Services; using MediaBrowser.Model.System; using MediaBrowser.Model.Tasks; -using MediaBrowser.Model.Threading; using MediaBrowser.Model.Updates; using MediaBrowser.Model.Xml; using MediaBrowser.Providers.Chapters; @@ -110,7 +107,6 @@ using MediaBrowser.XbmcMetadata.Providers; using Microsoft.Extensions.Logging; using ServiceStack; using ServiceStack.Text.Jsv; -using StringExtensions = MediaBrowser.Controller.Extensions.StringExtensions; using X509Certificate = System.Security.Cryptography.X509Certificates.X509Certificate; namespace Emby.Server.Implementations @@ -141,7 +137,7 @@ namespace Emby.Server.Implementations return false; } - if (StartupOptions.ContainsOption("-service")) + if (StartupOptions.IsService) { return false; } @@ -302,7 +298,7 @@ namespace Emby.Server.Implementations private ILiveTvManager LiveTvManager { get; set; } - public ILocalizationManager LocalizationManager { get; set; } + public LocalizationManager LocalizationManager { get; set; } private IEncodingManager EncodingManager { get; set; } private IChannelManager ChannelManager { get; set; } @@ -343,12 +339,11 @@ namespace Emby.Server.Implementations protected IHttpResultFactory HttpResultFactory { get; private set; } protected IAuthService AuthService { get; private set; } - public StartupOptions StartupOptions { get; private set; } + public IStartupOptions StartupOptions { get; private set; } internal IImageEncoder ImageEncoder { get; private set; } protected IProcessFactory ProcessFactory { get; private set; } - protected ITimerFactory TimerFactory { get; private set; } protected ICryptoProvider CryptographyProvider = new CryptographyProvider(); protected readonly IXmlSerializer XmlSerializer; @@ -364,7 +359,7 @@ namespace Emby.Server.Implementations /// </summary> public ApplicationHost(ServerApplicationPaths applicationPaths, ILoggerFactory loggerFactory, - StartupOptions options, + IStartupOptions options, IFileSystem fileSystem, IEnvironmentInfo environmentInfo, IImageEncoder imageEncoder, @@ -646,8 +641,10 @@ namespace Emby.Server.Implementations /// <summary> /// Runs the startup tasks. /// </summary> - public Task RunStartupTasks() + public async Task RunStartupTasks() { + Logger.LogInformation("Running startup tasks"); + Resolve<ITaskManager>().AddTasks(GetExports<IScheduledTask>(false)); ConfigurationManager.ConfigurationUpdated += OnConfigurationUpdated; @@ -666,20 +663,20 @@ namespace Emby.Server.Implementations Logger.LogInformation("ServerId: {0}", SystemId); var entryPoints = GetExports<IServerEntryPoint>(); - RunEntryPoints(entryPoints, true); + + var now = DateTime.UtcNow; + await Task.WhenAll(StartEntryPoints(entryPoints, true)); + Logger.LogInformation("Executed all pre-startup entry points in {Elapsed:fff} ms", DateTime.Now - now); Logger.LogInformation("Core startup complete"); HttpServer.GlobalResponse = null; - Logger.LogInformation("Post-init migrations complete"); - - RunEntryPoints(entryPoints, false); - Logger.LogInformation("All entry points have started"); - - return Task.CompletedTask; + now = DateTime.UtcNow; + await Task.WhenAll(StartEntryPoints(entryPoints, false)); + Logger.LogInformation("Executed all post-startup entry points in {Elapsed:fff} ms", DateTime.Now - now); } - private void RunEntryPoints(IEnumerable<IServerEntryPoint> entryPoints, bool isBeforeStartup) + private IEnumerable<Task> StartEntryPoints(IEnumerable<IServerEntryPoint> entryPoints, bool isBeforeStartup) { foreach (var entryPoint in entryPoints) { @@ -688,22 +685,13 @@ namespace Emby.Server.Implementations continue; } - var name = entryPoint.GetType().FullName; - Logger.LogInformation("Starting entry point {Name}", name); - var now = DateTime.UtcNow; - try - { - entryPoint.Run(); - } - catch (Exception ex) - { - Logger.LogError(ex, "Error while running entrypoint {Name}", name); - } - Logger.LogInformation("Entry point completed: {Name}. Duration: {Duration} seconds", name, (DateTime.UtcNow - now).TotalSeconds.ToString(CultureInfo.InvariantCulture), "ImageInfos"); + Logger.LogDebug("Starting entry point {Type}", entryPoint.GetType()); + + yield return entryPoint.RunAsync(); } } - public void Init() + public async Task Init() { HttpPort = ServerConfigurationManager.Configuration.HttpServerPortNumber; HttpsPort = ServerConfigurationManager.Configuration.HttpsPortNumber; @@ -733,7 +721,7 @@ namespace Emby.Server.Implementations SetHttpLimit(); - RegisterResources(); + await RegisterResources(); FindParts(); } @@ -748,7 +736,7 @@ namespace Emby.Server.Implementations /// <summary> /// Registers resources that classes will depend on /// </summary> - protected void RegisterResources() + protected async Task RegisterResources() { RegisterSingleInstance(ConfigurationManager); RegisterSingleInstance<IApplicationHost>(this); @@ -780,9 +768,6 @@ namespace Emby.Server.Implementations ProcessFactory = new ProcessFactory(); RegisterSingleInstance(ProcessFactory); - TimerFactory = new TimerFactory(); - RegisterSingleInstance(TimerFactory); - var streamHelper = CreateStreamHelper(); ApplicationHost.StreamHelper = streamHelper; RegisterSingleInstance(streamHelper); @@ -809,9 +794,9 @@ namespace Emby.Server.Implementations IAssemblyInfo assemblyInfo = new AssemblyInfo(); RegisterSingleInstance(assemblyInfo); - LocalizationManager = new LocalizationManager(ServerConfigurationManager, FileSystemManager, JsonSerializer, LoggerFactory, assemblyInfo, new TextLocalizer()); - StringExtensions.LocalizationManager = LocalizationManager; - RegisterSingleInstance(LocalizationManager); + LocalizationManager = new LocalizationManager(ServerConfigurationManager, FileSystemManager, JsonSerializer, LoggerFactory); + await LocalizationManager.LoadAll(); + RegisterSingleInstance<ILocalizationManager>(LocalizationManager); BlurayExaminer = new BdInfoExaminer(FileSystemManager); RegisterSingleInstance(BlurayExaminer); @@ -845,7 +830,7 @@ namespace Emby.Server.Implementations var musicManager = new MusicManager(LibraryManager); RegisterSingleInstance<IMusicManager>(new MusicManager(LibraryManager)); - LibraryMonitor = new LibraryMonitor(LoggerFactory, TaskManager, LibraryManager, ServerConfigurationManager, FileSystemManager, TimerFactory, EnvironmentInfo); + LibraryMonitor = new LibraryMonitor(LoggerFactory, TaskManager, LibraryManager, ServerConfigurationManager, FileSystemManager, EnvironmentInfo); RegisterSingleInstance(LibraryMonitor); RegisterSingleInstance<ISearchEngine>(() => new SearchEngine(LoggerFactory, LibraryManager, UserManager)); @@ -877,7 +862,7 @@ namespace Emby.Server.Implementations DeviceManager = new DeviceManager(AuthenticationRepository, JsonSerializer, LibraryManager, LocalizationManager, UserManager, FileSystemManager, LibraryMonitor, ServerConfigurationManager, LoggerFactory, NetworkManager); RegisterSingleInstance(DeviceManager); - MediaSourceManager = new MediaSourceManager(ItemRepository, ApplicationPaths, LocalizationManager, UserManager, LibraryManager, LoggerFactory, JsonSerializer, FileSystemManager, UserDataManager, TimerFactory, () => MediaEncoder); + MediaSourceManager = new MediaSourceManager(ItemRepository, ApplicationPaths, LocalizationManager, UserManager, LibraryManager, LoggerFactory, JsonSerializer, FileSystemManager, UserDataManager, () => MediaEncoder); RegisterSingleInstance(MediaSourceManager); SubtitleManager = new SubtitleManager(LoggerFactory, FileSystemManager, LibraryMonitor, MediaSourceManager, LocalizationManager); @@ -892,7 +877,7 @@ namespace Emby.Server.Implementations ChannelManager = new ChannelManager(UserManager, DtoService, LibraryManager, LoggerFactory, ServerConfigurationManager, FileSystemManager, UserDataManager, JsonSerializer, LocalizationManager, HttpClient, ProviderManager); RegisterSingleInstance(ChannelManager); - SessionManager = new SessionManager(UserDataManager, LoggerFactory, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, JsonSerializer, this, HttpClient, AuthenticationRepository, DeviceManager, MediaSourceManager, TimerFactory); + SessionManager = new SessionManager(UserDataManager, LoggerFactory, LibraryManager, UserManager, musicManager, DtoService, ImageProcessor, JsonSerializer, this, HttpClient, AuthenticationRepository, DeviceManager, MediaSourceManager); RegisterSingleInstance(SessionManager); var dlnaManager = new DlnaManager(XmlSerializer, FileSystemManager, ApplicationPaths, LoggerFactory, JsonSerializer, this, assemblyInfo); @@ -904,7 +889,7 @@ namespace Emby.Server.Implementations PlaylistManager = new PlaylistManager(LibraryManager, FileSystemManager, LibraryMonitor, LoggerFactory, UserManager, ProviderManager); RegisterSingleInstance(PlaylistManager); - LiveTvManager = new LiveTvManager(this, ServerConfigurationManager, LoggerFactory, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager, LocalizationManager, JsonSerializer, ProviderManager, FileSystemManager, () => ChannelManager); + LiveTvManager = new LiveTvManager(this, ServerConfigurationManager, LoggerFactory, ItemRepository, ImageProcessor, UserDataManager, DtoService, UserManager, LibraryManager, TaskManager, LocalizationManager, JsonSerializer, FileSystemManager, () => ChannelManager); RegisterSingleInstance(LiveTvManager); UserViewManager = new UserViewManager(LibraryManager, LocalizationManager, UserManager, ChannelManager, LiveTvManager, ServerConfigurationManager); @@ -913,7 +898,7 @@ namespace Emby.Server.Implementations NotificationManager = new NotificationManager(LoggerFactory, UserManager, ServerConfigurationManager); RegisterSingleInstance(NotificationManager); - RegisterSingleInstance<IDeviceDiscovery>(new DeviceDiscovery(LoggerFactory, ServerConfigurationManager, SocketFactory, TimerFactory)); + RegisterSingleInstance<IDeviceDiscovery>(new DeviceDiscovery(LoggerFactory, ServerConfigurationManager, SocketFactory)); ChapterManager = new ChapterManager(LibraryManager, LoggerFactory, ServerConfigurationManager, ItemRepository); RegisterSingleInstance(ChapterManager); @@ -1671,7 +1656,6 @@ namespace Emby.Server.Implementations var minRequiredVersions = new Dictionary<string, Version>(StringComparer.OrdinalIgnoreCase) { - { "GameBrowser.dll", new Version(3, 1) }, { "moviethemesongs.dll", new Version(1, 6) }, { "themesongs.dll", new Version(1, 2) } }; @@ -1747,7 +1731,7 @@ namespace Emby.Server.Implementations EncoderLocationType = MediaEncoder.EncoderLocationType, SystemArchitecture = EnvironmentInfo.SystemArchitecture, SystemUpdateLevel = SystemUpdateLevel, - PackageName = StartupOptions.GetOption("-package") + PackageName = StartupOptions.PackageName }; } diff --git a/Emby.Server.Implementations/Collections/CollectionImageProvider.cs b/Emby.Server.Implementations/Collections/CollectionImageProvider.cs index 6642d1ef4..6aeadda2f 100644 --- a/Emby.Server.Implementations/Collections/CollectionImageProvider.cs +++ b/Emby.Server.Implementations/Collections/CollectionImageProvider.cs @@ -70,7 +70,8 @@ namespace Emby.Server.Implementations.Collections return null; }) .Where(i => i != null) - .DistinctBy(i => i.Id) + .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 c8b822970..812e48a1f 100644 --- a/Emby.Server.Implementations/Collections/CollectionManager.cs +++ b/Emby.Server.Implementations/Collections/CollectionManager.cs @@ -353,7 +353,7 @@ namespace Emby.Server.Implementations.Collections _logger = logger; } - public async void Run() + public async Task RunAsync() { if (!_config.Configuration.CollectionsUpgraded && _config.Configuration.IsStartupWizardCompleted) { diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs index 3de4da444..3014e482d 100644 --- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs +++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs @@ -1239,10 +1239,6 @@ namespace Emby.Server.Implementations.Data { return false; } - else if (type == typeof(GameGenre)) - { - return false; - } else if (type == typeof(Genre)) { return false; @@ -3905,7 +3901,7 @@ namespace Emby.Server.Implementations.Data // lowercase this because SortName is stored as lowercase if (statement != null) { - statement.TryBind("@NameStartsWithOrGreater", query.NameStartsWithOrGreater.ToLower()); + statement.TryBind("@NameStartsWithOrGreater", query.NameStartsWithOrGreater.ToLowerInvariant()); } } if (!string.IsNullOrWhiteSpace(query.NameLessThan)) @@ -3914,7 +3910,7 @@ namespace Emby.Server.Implementations.Data // lowercase this because SortName is stored as lowercase if (statement != null) { - statement.TryBind("@NameLessThan", query.NameLessThan.ToLower()); + statement.TryBind("@NameLessThan", query.NameLessThan.ToLowerInvariant()); } } @@ -4789,10 +4785,6 @@ namespace Emby.Server.Implementations.Data { list.Add(typeof(MusicGenre).Name); } - if (IsTypeInQuery(typeof(GameGenre).Name, query)) - { - list.Add(typeof(GameGenre).Name); - } if (IsTypeInQuery(typeof(MusicArtist).Name, query)) { list.Add(typeof(MusicArtist).Name); @@ -4822,7 +4814,7 @@ namespace Emby.Server.Implementations.Data return value; } - return value.RemoveDiacritics().ToLower(); + return value.RemoveDiacritics().ToLowerInvariant(); } private bool EnableGroupByPresentationUniqueKey(InternalItemsQuery query) @@ -4891,9 +4883,6 @@ namespace Emby.Server.Implementations.Data typeof(Book), typeof(CollectionFolder), typeof(Folder), - typeof(Game), - typeof(GameGenre), - typeof(GameSystem), typeof(Genre), typeof(Person), typeof(Photo), @@ -5251,11 +5240,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type return GetItemValues(query, new[] { 2 }, typeof(Genre).FullName); } - public QueryResult<Tuple<BaseItem, ItemCounts>> GetGameGenres(InternalItemsQuery query) - { - return GetItemValues(query, new[] { 2 }, typeof(GameGenre).FullName); - } - public QueryResult<Tuple<BaseItem, ItemCounts>> GetMusicGenres(InternalItemsQuery query) { return GetItemValues(query, new[] { 2 }, typeof(MusicGenre).FullName); @@ -5276,14 +5260,9 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type return GetItemValueNames(new[] { 2 }, new List<string> { "Audio", "MusicVideo", "MusicAlbum", "MusicArtist" }, new List<string>()); } - public List<string> GetGameGenreNames() - { - return GetItemValueNames(new[] { 2 }, new List<string> { "Game" }, new List<string>()); - } - public List<string> GetGenreNames() { - return GetItemValueNames(new[] { 2 }, new List<string>(), new List<string> { "Audio", "MusicVideo", "MusicAlbum", "MusicArtist", "Game", "GameSystem" }); + return GetItemValueNames(new[] { 2 }, new List<string>(), new List<string> { "Audio", "MusicVideo", "MusicAlbum", "MusicArtist" }); } private List<string> GetItemValueNames(int[] itemValueTypes, List<string> withItemTypes, List<string> excludeItemTypes) @@ -5652,10 +5631,6 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type { counts.SongCount = value; } - else if (string.Equals(typeName, typeof(Game).FullName, StringComparison.OrdinalIgnoreCase)) - { - counts.GameCount = value; - } else if (string.Equals(typeName, typeof(Trailer).FullName, StringComparison.OrdinalIgnoreCase)) { counts.TrailerCount = value; diff --git a/Emby.Server.Implementations/Devices/DeviceManager.cs b/Emby.Server.Implementations/Devices/DeviceManager.cs index e94a649bf..ec3649bca 100644 --- a/Emby.Server.Implementations/Devices/DeviceManager.cs +++ b/Emby.Server.Implementations/Devices/DeviceManager.cs @@ -425,7 +425,7 @@ namespace Emby.Server.Implementations.Devices _logger = logger; } - public async void Run() + public async Task RunAsync() { if (!_config.Configuration.CameraUploadUpgraded && _config.Configuration.IsStartupWizardCompleted) { diff --git a/Emby.Server.Implementations/Diagnostics/CommonProcess.cs b/Emby.Server.Implementations/Diagnostics/CommonProcess.cs index 55539eafc..78b22bda3 100644 --- a/Emby.Server.Implementations/Diagnostics/CommonProcess.cs +++ b/Emby.Server.Implementations/Diagnostics/CommonProcess.cs @@ -105,7 +105,7 @@ namespace Emby.Server.Implementations.Diagnostics { return _process.WaitForExit(timeMs); } - + public Task<bool> WaitForExitAsync(int timeMs) { //Note: For this function to work correctly, the option EnableRisingEvents needs to be set to true. diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index d0a7de11d..983eb51e6 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -374,10 +374,6 @@ namespace Emby.Server.Implementations.Dto dto.MusicVideoCount = taggedItems.Count(i => i is MusicVideo); dto.SongCount = taggedItems.Count(i => i is Audio); } - else if (item is GameGenre) - { - dto.GameCount = taggedItems.Count(i => i is Game); - } else { // This populates them all and covers Genre, Person, Studio, Year @@ -385,7 +381,6 @@ namespace Emby.Server.Implementations.Dto dto.ArtistCount = taggedItems.Count(i => i is MusicArtist); dto.AlbumCount = taggedItems.Count(i => i is MusicAlbum); dto.EpisodeCount = taggedItems.Count(i => i is Episode); - dto.GameCount = taggedItems.Count(i => i is Game); dto.MovieCount = taggedItems.Count(i => i is Movie); dto.TrailerCount = taggedItems.Count(i => i is Trailer); dto.MusicVideoCount = taggedItems.Count(i => i is MusicVideo); @@ -532,17 +527,6 @@ namespace Emby.Server.Implementations.Dto dto.Album = item.Album; } - private static void SetGameProperties(BaseItemDto dto, Game item) - { - dto.GameSystem = item.GameSystem; - dto.MultiPartGameFiles = item.MultiPartGameFiles; - } - - private static void SetGameSystemProperties(BaseItemDto dto, GameSystem item) - { - dto.GameSystem = item.GameSystemName; - } - private string[] GetImageTags(BaseItem item, List<ItemImageInfo> images) { return images @@ -636,7 +620,8 @@ namespace Emby.Server.Implementations.Dto } }).Where(i => i != null) - .DistinctBy(i => i.Name, StringComparer.OrdinalIgnoreCase) + .GroupBy(i => i.Name, StringComparer.OrdinalIgnoreCase) + .Select(x => x.First()) .ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase); for (var i = 0; i < people.Count; i++) @@ -698,11 +683,6 @@ namespace Emby.Server.Implementations.Dto return _libraryManager.GetMusicGenreId(name); } - if (owner is Game || owner is GameSystem) - { - return _libraryManager.GetGameGenreId(name); - } - return _libraryManager.GetGenreId(name); } @@ -1206,20 +1186,6 @@ namespace Emby.Server.Implementations.Dto } } - var game = item as Game; - - if (game != null) - { - SetGameProperties(dto, game); - } - - var gameSystem = item as GameSystem; - - if (gameSystem != null) - { - SetGameSystemProperties(dto, gameSystem); - } - var musicVideo = item as MusicVideo; if (musicVideo != null) { @@ -1452,7 +1418,7 @@ namespace Emby.Server.Implementations.Dto try { - size = _imageProcessor.GetImageSize(item, imageInfo); + size = _imageProcessor.GetImageDimensions(item, imageInfo); if (size.Width <= 0 || size.Height <= 0) { diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index df7963b02..86b2efe54 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -1,4 +1,4 @@ -<Project Sdk="Microsoft.NET.Sdk"> +<Project Sdk="Microsoft.NET.Sdk"> <ItemGroup> <ProjectReference Include="..\Emby.Naming\Emby.Naming.csproj" /> @@ -25,8 +25,7 @@ <PackageReference Include="ServiceStack.Text.Core" Version="5.4.0" /> <PackageReference Include="sharpcompress" Version="0.22.0" /> <PackageReference Include="SimpleInjector" Version="4.4.2" /> - <PackageReference Include="SQLitePCL.pretty.core" Version="1.1.8" /> - <PackageReference Include="SQLitePCLRaw.core" Version="1.1.11" /> + <PackageReference Include="SQLitePCL.pretty.netstandard" Version="1.0.0" /> <PackageReference Include="UTF.Unknown" Version="1.0.0-beta1" /> </ItemGroup> @@ -43,7 +42,7 @@ <EmbeddedResource Include="Localization\iso6392.txt" /> <EmbeddedResource Include="Localization\countries.json" /> <EmbeddedResource Include="Localization\Core\*.json" /> - <EmbeddedResource Include="Localization\Ratings\*.txt" /> + <EmbeddedResource Include="Localization\Ratings\*.csv" /> </ItemGroup> </Project> diff --git a/Emby.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs b/Emby.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs index 0fc4c3858..19ea09359 100644 --- a/Emby.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs +++ b/Emby.Server.Implementations/EntryPoints/AutomaticRestartEntryPoint.cs @@ -9,7 +9,6 @@ using MediaBrowser.Controller.Plugins; using MediaBrowser.Controller.Session; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Tasks; -using MediaBrowser.Model.Threading; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.EntryPoints @@ -22,11 +21,10 @@ namespace Emby.Server.Implementations.EntryPoints private readonly ISessionManager _sessionManager; private readonly IServerConfigurationManager _config; private readonly ILiveTvManager _liveTvManager; - private readonly ITimerFactory _timerFactory; - private ITimer _timer; + private Timer _timer; - public AutomaticRestartEntryPoint(IServerApplicationHost appHost, ILogger logger, ITaskManager iTaskManager, ISessionManager sessionManager, IServerConfigurationManager config, ILiveTvManager liveTvManager, ITimerFactory timerFactory) + public AutomaticRestartEntryPoint(IServerApplicationHost appHost, ILogger logger, ITaskManager iTaskManager, ISessionManager sessionManager, IServerConfigurationManager config, ILiveTvManager liveTvManager) { _appHost = appHost; _logger = logger; @@ -34,15 +32,16 @@ namespace Emby.Server.Implementations.EntryPoints _sessionManager = sessionManager; _config = config; _liveTvManager = liveTvManager; - _timerFactory = timerFactory; } - public void Run() + public Task RunAsync() { if (_appHost.CanSelfRestart) { _appHost.HasPendingRestartChanged += _appHost_HasPendingRestartChanged; } + + return Task.CompletedTask; } void _appHost_HasPendingRestartChanged(object sender, EventArgs e) @@ -51,7 +50,7 @@ namespace Emby.Server.Implementations.EntryPoints if (_appHost.HasPendingRestart) { - _timer = _timerFactory.Create(TimerCallback, null, TimeSpan.FromMinutes(15), TimeSpan.FromMinutes(15)); + _timer = new Timer(TimerCallback, null, TimeSpan.FromMinutes(15), TimeSpan.FromMinutes(15)); } } diff --git a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs index 8755ee3a7..f26a70586 100644 --- a/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs +++ b/Emby.Server.Implementations/EntryPoints/ExternalPortForwarding.cs @@ -10,7 +10,6 @@ using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Plugins; using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Events; -using MediaBrowser.Model.Threading; using Microsoft.Extensions.Logging; using Mono.Nat; @@ -24,19 +23,17 @@ namespace Emby.Server.Implementations.EntryPoints private readonly IServerConfigurationManager _config; private readonly IDeviceDiscovery _deviceDiscovery; - private ITimer _timer; - private readonly ITimerFactory _timerFactory; + private Timer _timer; private NatManager _natManager; - public ExternalPortForwarding(ILoggerFactory loggerFactory, IServerApplicationHost appHost, IServerConfigurationManager config, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient, ITimerFactory timerFactory) + public ExternalPortForwarding(ILoggerFactory loggerFactory, IServerApplicationHost appHost, IServerConfigurationManager config, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient) { _logger = loggerFactory.CreateLogger("PortMapper"); _appHost = appHost; _config = config; _deviceDiscovery = deviceDiscovery; _httpClient = httpClient; - _timerFactory = timerFactory; _config.ConfigurationUpdated += _config_ConfigurationUpdated1; } @@ -61,17 +58,17 @@ namespace Emby.Server.Implementations.EntryPoints return string.Join("|", values.ToArray()); } - void _config_ConfigurationUpdated(object sender, EventArgs e) + private async void _config_ConfigurationUpdated(object sender, EventArgs e) { if (!string.Equals(_lastConfigIdentifier, GetConfigIdentifier(), StringComparison.OrdinalIgnoreCase)) { DisposeNat(); - Run(); + await RunAsync(); } } - public void Run() + public Task RunAsync() { if (_config.Configuration.EnableUPnP && _config.Configuration.EnableRemoteAccess) { @@ -80,6 +77,8 @@ namespace Emby.Server.Implementations.EntryPoints _config.ConfigurationUpdated -= _config_ConfigurationUpdated; _config.ConfigurationUpdated += _config_ConfigurationUpdated; + + return Task.CompletedTask; } private void Start() @@ -92,7 +91,7 @@ namespace Emby.Server.Implementations.EntryPoints _natManager.StartDiscovery(); } - _timer = _timerFactory.Create(ClearCreatedRules, null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10)); + _timer = new Timer(ClearCreatedRules, null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10)); _deviceDiscovery.DeviceDiscovered += _deviceDiscovery_DeviceDiscovered; diff --git a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs index 7a8b09cf7..038965647 100644 --- a/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Threading; +using System.Threading.Tasks; using MediaBrowser.Controller.Channels; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; @@ -13,7 +14,6 @@ using MediaBrowser.Controller.Session; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Events; using MediaBrowser.Model.Extensions; -using MediaBrowser.Model.Threading; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.EntryPoints @@ -28,7 +28,6 @@ namespace Emby.Server.Implementations.EntryPoints private readonly ISessionManager _sessionManager; private readonly IUserManager _userManager; private readonly ILogger _logger; - private readonly ITimerFactory _timerFactory; /// <summary> /// The _library changed sync lock @@ -46,7 +45,7 @@ namespace Emby.Server.Implementations.EntryPoints /// Gets or sets the library update timer. /// </summary> /// <value>The library update timer.</value> - private ITimer LibraryUpdateTimer { get; set; } + private Timer LibraryUpdateTimer { get; set; } /// <summary> /// The library update duration @@ -55,17 +54,16 @@ namespace Emby.Server.Implementations.EntryPoints private readonly IProviderManager _providerManager; - public LibraryChangedNotifier(ILibraryManager libraryManager, ISessionManager sessionManager, IUserManager userManager, ILogger logger, ITimerFactory timerFactory, IProviderManager providerManager) + public LibraryChangedNotifier(ILibraryManager libraryManager, ISessionManager sessionManager, IUserManager userManager, ILogger logger, IProviderManager providerManager) { _libraryManager = libraryManager; _sessionManager = sessionManager; _userManager = userManager; _logger = logger; - _timerFactory = timerFactory; _providerManager = providerManager; } - public void Run() + public Task RunAsync() { _libraryManager.ItemAdded += libraryManager_ItemAdded; _libraryManager.ItemUpdated += libraryManager_ItemUpdated; @@ -74,6 +72,8 @@ namespace Emby.Server.Implementations.EntryPoints _providerManager.RefreshCompleted += _providerManager_RefreshCompleted; _providerManager.RefreshStarted += _providerManager_RefreshStarted; _providerManager.RefreshProgress += _providerManager_RefreshProgress; + + return Task.CompletedTask; } private Dictionary<Guid, DateTime> _lastProgressMessageTimes = new Dictionary<Guid, DateTime>(); @@ -188,7 +188,7 @@ namespace Emby.Server.Implementations.EntryPoints { if (LibraryUpdateTimer == null) { - LibraryUpdateTimer = _timerFactory.Create(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, + LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, Timeout.Infinite); } else @@ -222,7 +222,7 @@ namespace Emby.Server.Implementations.EntryPoints { if (LibraryUpdateTimer == null) { - LibraryUpdateTimer = _timerFactory.Create(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, + LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, Timeout.Infinite); } else @@ -250,7 +250,7 @@ namespace Emby.Server.Implementations.EntryPoints { if (LibraryUpdateTimer == null) { - LibraryUpdateTimer = _timerFactory.Create(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, + LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, Timeout.Infinite); } else @@ -277,14 +277,21 @@ namespace Emby.Server.Implementations.EntryPoints lock (_libraryChangedSyncLock) { // Remove dupes in case some were saved multiple times - var foldersAddedTo = _foldersAddedTo.DistinctBy(i => i.Id).ToList(); + var foldersAddedTo = _foldersAddedTo + .GroupBy(x => x.Id) + .Select(x => x.First()) + .ToList(); - var foldersRemovedFrom = _foldersRemovedFrom.DistinctBy(i => i.Id).ToList(); + var foldersRemovedFrom = _foldersRemovedFrom + .GroupBy(x => x.Id) + .Select(x => x.First()) + .ToList(); var itemsUpdated = _itemsUpdated - .Where(i => !_itemsAdded.Contains(i)) - .DistinctBy(i => i.Id) - .ToList(); + .Where(i => !_itemsAdded.Contains(i)) + .GroupBy(x => x.Id) + .Select(x => x.First()) + .ToList(); SendChangeNotifications(_itemsAdded.ToList(), itemsUpdated, _itemsRemoved.ToList(), foldersAddedTo, foldersRemovedFrom, CancellationToken.None); diff --git a/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs b/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs index e37ea96a1..0186da9e1 100644 --- a/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Threading; +using System.Threading.Tasks; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Controller.Plugins; @@ -24,12 +25,14 @@ namespace Emby.Server.Implementations.EntryPoints _liveTvManager = liveTvManager; } - public void Run() + public Task RunAsync() { _liveTvManager.TimerCancelled += _liveTvManager_TimerCancelled; _liveTvManager.SeriesTimerCancelled += _liveTvManager_SeriesTimerCancelled; _liveTvManager.TimerCreated += _liveTvManager_TimerCreated; _liveTvManager.SeriesTimerCreated += _liveTvManager_SeriesTimerCreated; + + return Task.CompletedTask; } private void _liveTvManager_SeriesTimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e) diff --git a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs index 92ea3a8f4..091dd6a45 100644 --- a/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/ServerEventNotifier.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Threading; +using System.Threading.Tasks; using MediaBrowser.Common.Plugins; using MediaBrowser.Common.Updates; using MediaBrowser.Controller; @@ -49,7 +50,7 @@ namespace Emby.Server.Implementations.EntryPoints _sessionManager = sessionManager; } - public void Run() + public Task RunAsync() { _userManager.UserDeleted += userManager_UserDeleted; _userManager.UserUpdated += userManager_UserUpdated; @@ -65,6 +66,8 @@ namespace Emby.Server.Implementations.EntryPoints _installationManager.PackageInstallationFailed += _installationManager_PackageInstallationFailed; _taskManager.TaskCompleted += _taskManager_TaskCompleted; + + return Task.CompletedTask; } void _installationManager_PackageInstalling(object sender, InstallationEventArgs e) diff --git a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs index 05c8b07ab..8be6db87d 100644 --- a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs +++ b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs @@ -1,3 +1,4 @@ +using System.Threading.Tasks; using Emby.Server.Implementations.Browser; using MediaBrowser.Controller; using MediaBrowser.Controller.Configuration; @@ -32,11 +33,11 @@ namespace Emby.Server.Implementations.EntryPoints /// <summary> /// Runs this instance. /// </summary> - public void Run() + public Task RunAsync() { if (!_appHost.CanLaunchWebBrowser) { - return; + return Task.CompletedTask; } if (!_config.Configuration.IsStartupWizardCompleted) @@ -47,11 +48,13 @@ namespace Emby.Server.Implementations.EntryPoints { var options = ((ApplicationHost)_appHost).StartupOptions; - if (!options.ContainsOption("-noautorunwebapp")) + if (!options.NoAutoRunWebApp) { BrowserLauncher.OpenWebApp(_appHost); } } + + return Task.CompletedTask; } /// <summary> diff --git a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs index 2c8246d13..5b90dc1fb 100644 --- a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs +++ b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using Emby.Server.Implementations.Udp; using MediaBrowser.Controller; using MediaBrowser.Controller.Plugins; @@ -43,7 +44,7 @@ namespace Emby.Server.Implementations.EntryPoints /// <summary> /// Runs this instance. /// </summary> - public void Run() + public Task RunAsync() { var udpServer = new UdpServer(_logger, _appHost, _json, _socketFactory); @@ -57,6 +58,8 @@ namespace Emby.Server.Implementations.EntryPoints { _logger.LogError(ex, "Failed to start UDP Server"); } + + return Task.CompletedTask; } /// <summary> diff --git a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs index 9e71ffceb..774ed09da 100644 --- a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs +++ b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs @@ -10,7 +10,6 @@ using MediaBrowser.Controller.Session; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Session; -using MediaBrowser.Model.Threading; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.EntryPoints @@ -23,24 +22,24 @@ namespace Emby.Server.Implementations.EntryPoints private readonly IUserManager _userManager; private readonly object _syncLock = new object(); - private ITimer UpdateTimer { get; set; } - private readonly ITimerFactory _timerFactory; + 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, ITimerFactory timerFactory) + public UserDataChangeNotifier(IUserDataManager userDataManager, ISessionManager sessionManager, ILogger logger, IUserManager userManager) { _userDataManager = userDataManager; _sessionManager = sessionManager; _logger = logger; _userManager = userManager; - _timerFactory = timerFactory; } - public void Run() + public Task RunAsync() { _userDataManager.UserDataSaved += _userDataManager_UserDataSaved; + + return Task.CompletedTask; } void _userDataManager_UserDataSaved(object sender, UserDataSaveEventArgs e) @@ -54,7 +53,7 @@ namespace Emby.Server.Implementations.EntryPoints { if (UpdateTimer == null) { - UpdateTimer = _timerFactory.Create(UpdateTimerCallback, null, UpdateDuration, + UpdateTimer = new Timer(UpdateTimerCallback, null, UpdateDuration, Timeout.Infinite); } else @@ -121,7 +120,8 @@ namespace Emby.Server.Implementations.EntryPoints var user = _userManager.GetUserById(userId); var dtoList = changedItems - .DistinctBy(i => i.Id) + .GroupBy(x => x.Id) + .Select(x => x.First()) .Select(i => { var dto = _userDataManager.GetUserDataDto(i, user); diff --git a/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs b/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs index 79a42f294..6167d1eaa 100644 --- a/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs +++ b/Emby.Server.Implementations/FFMpeg/FFMpegLoader.cs @@ -28,10 +28,10 @@ namespace Emby.Server.Implementations.FFMpeg _ffmpegInstallInfo = ffmpegInstallInfo; } - public FFMpegInfo GetFFMpegInfo(StartupOptions options) + public FFMpegInfo GetFFMpegInfo(IStartupOptions options) { - var customffMpegPath = options.GetOption("-ffmpeg"); - var customffProbePath = options.GetOption("-ffprobe"); + var customffMpegPath = options.FFmpegPath; + var customffProbePath = options.FFprobePath; if (!string.IsNullOrWhiteSpace(customffMpegPath) && !string.IsNullOrWhiteSpace(customffProbePath)) { diff --git a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs index a61247fd1..6ea1bd08e 100644 --- a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs +++ b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs @@ -264,7 +264,7 @@ namespace Emby.Server.Implementations.HttpClientManager } var url = options.Url; - var urlHash = url.ToLower().GetMD5().ToString("N"); + var urlHash = url.ToLowerInvariant().GetMD5().ToString("N"); var responseCachePath = Path.Combine(_appPaths.CachePath, "httpclient", urlHash); @@ -374,11 +374,11 @@ namespace Emby.Server.Implementations.HttpClientManager { if (options.LogRequestAsDebug) { - _logger.LogDebug("HttpClientManager {0}: {1}", httpMethod.ToUpper(), options.Url); + _logger.LogDebug("HttpClientManager {0}: {1}", httpMethod.ToUpper(CultureInfo.CurrentCulture), options.Url); } else { - _logger.LogInformation("HttpClientManager {0}: {1}", httpMethod.ToUpper(), options.Url); + _logger.LogInformation("HttpClientManager {0}: {1}", httpMethod.ToUpper(CultureInfo.CurrentCulture), options.Url); } } diff --git a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs index 0ad4d8406..7445fd3c2 100644 --- a/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs +++ b/Emby.Server.Implementations/HttpServer/HttpResultFactory.cs @@ -394,7 +394,7 @@ namespace Emby.Server.Implementations.HttpServer { return contentType == null ? null - : contentType.Split(';')[0].ToLower().Trim(); + : contentType.Split(';')[0].ToLowerInvariant().Trim(); } private static string SerializeToXmlString(object from) diff --git a/Emby.Server.Implementations/IO/FileRefresher.cs b/Emby.Server.Implementations/IO/FileRefresher.cs index 12532a497..3668f6a7a 100644 --- a/Emby.Server.Implementations/IO/FileRefresher.cs +++ b/Emby.Server.Implementations/IO/FileRefresher.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Threading; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; @@ -9,7 +10,6 @@ using MediaBrowser.Model.Extensions; using MediaBrowser.Model.IO; using MediaBrowser.Model.System; using MediaBrowser.Model.Tasks; -using MediaBrowser.Model.Threading; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.IO @@ -22,8 +22,7 @@ namespace Emby.Server.Implementations.IO private IServerConfigurationManager ConfigurationManager { get; set; } private readonly IFileSystem _fileSystem; private readonly List<string> _affectedPaths = new List<string>(); - private ITimer _timer; - private readonly ITimerFactory _timerFactory; + private Timer _timer; private readonly object _timerLock = new object(); public string Path { get; private set; } @@ -31,7 +30,7 @@ namespace Emby.Server.Implementations.IO private readonly IEnvironmentInfo _environmentInfo; private readonly ILibraryManager _libraryManager; - public FileRefresher(string path, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, ITaskManager taskManager, ILogger logger, ITimerFactory timerFactory, IEnvironmentInfo environmentInfo, ILibraryManager libraryManager1) + public FileRefresher(string path, IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, ITaskManager taskManager, ILogger logger, IEnvironmentInfo environmentInfo, ILibraryManager libraryManager1) { logger.LogDebug("New file refresher created for {0}", path); Path = path; @@ -41,7 +40,6 @@ namespace Emby.Server.Implementations.IO LibraryManager = libraryManager; TaskManager = taskManager; Logger = logger; - _timerFactory = timerFactory; _environmentInfo = environmentInfo; _libraryManager = libraryManager1; AddPath(path); @@ -90,7 +88,7 @@ namespace Emby.Server.Implementations.IO if (_timer == null) { - _timer = _timerFactory.Create(OnTimerCallback, null, TimeSpan.FromSeconds(ConfigurationManager.Configuration.LibraryMonitorDelay), TimeSpan.FromMilliseconds(-1)); + _timer = new Timer(OnTimerCallback, null, TimeSpan.FromSeconds(ConfigurationManager.Configuration.LibraryMonitorDelay), TimeSpan.FromMilliseconds(-1)); } else { @@ -146,8 +144,8 @@ namespace Emby.Server.Implementations.IO .Distinct(StringComparer.OrdinalIgnoreCase) .Select(GetAffectedBaseItem) .Where(item => item != null) - .DistinctBy(i => i.Id) - .ToList(); + .GroupBy(x => x.Id) + .Select(x => x.First()); foreach (var item in itemsToRefresh) { diff --git a/Emby.Server.Implementations/IO/LibraryMonitor.cs b/Emby.Server.Implementations/IO/LibraryMonitor.cs index dad81c195..607a4d333 100644 --- a/Emby.Server.Implementations/IO/LibraryMonitor.cs +++ b/Emby.Server.Implementations/IO/LibraryMonitor.cs @@ -11,7 +11,6 @@ using MediaBrowser.Controller.Plugins; using MediaBrowser.Model.IO; using MediaBrowser.Model.System; using MediaBrowser.Model.Tasks; -using MediaBrowser.Model.Threading; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.IO @@ -35,7 +34,7 @@ namespace Emby.Server.Implementations.IO /// <summary> /// Any file name ending in any of these will be ignored by the watchers /// </summary> - private readonly string[] _alwaysIgnoreFiles = new string[] + private readonly HashSet<string> _alwaysIgnoreFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "small.jpg", "albumart.jpg", @@ -54,7 +53,7 @@ namespace Emby.Server.Implementations.IO ".actors" }; - private readonly string[] _alwaysIgnoreExtensions = new string[] + private readonly HashSet<string> _alwaysIgnoreExtensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { // thumbs.db ".db", @@ -134,7 +133,6 @@ namespace Emby.Server.Implementations.IO private IServerConfigurationManager ConfigurationManager { get; set; } private readonly IFileSystem _fileSystem; - private readonly ITimerFactory _timerFactory; private readonly IEnvironmentInfo _environmentInfo; /// <summary> @@ -146,7 +144,6 @@ namespace Emby.Server.Implementations.IO ILibraryManager libraryManager, IServerConfigurationManager configurationManager, IFileSystem fileSystem, - ITimerFactory timerFactory, IEnvironmentInfo environmentInfo) { if (taskManager == null) @@ -159,7 +156,6 @@ namespace Emby.Server.Implementations.IO Logger = loggerFactory.CreateLogger(GetType().Name); ConfigurationManager = configurationManager; _fileSystem = fileSystem; - _timerFactory = timerFactory; _environmentInfo = environmentInfo; } @@ -460,8 +456,8 @@ namespace Emby.Server.Implementations.IO var filename = Path.GetFileName(path); var monitorPath = !string.IsNullOrEmpty(filename) && - !_alwaysIgnoreFiles.Contains(filename, StringComparer.OrdinalIgnoreCase) && - !_alwaysIgnoreExtensions.Contains(Path.GetExtension(path) ?? string.Empty, StringComparer.OrdinalIgnoreCase) && + !_alwaysIgnoreFiles.Contains(filename) && + !_alwaysIgnoreExtensions.Contains(Path.GetExtension(path)) && _alwaysIgnoreSubstrings.All(i => path.IndexOf(i, StringComparison.OrdinalIgnoreCase) == -1); // Ignore certain files @@ -545,7 +541,7 @@ namespace Emby.Server.Implementations.IO } } - var newRefresher = new FileRefresher(path, _fileSystem, ConfigurationManager, LibraryManager, TaskManager, Logger, _timerFactory, _environmentInfo, LibraryManager); + var newRefresher = new FileRefresher(path, _fileSystem, ConfigurationManager, LibraryManager, TaskManager, Logger, _environmentInfo, LibraryManager); newRefresher.Completed += NewRefresher_Completed; _activeRefreshers.Add(newRefresher); } @@ -601,20 +597,26 @@ namespace Emby.Server.Implementations.IO /// </summary> public void Dispose() { - _disposed = true; Dispose(true); } /// <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 dispose) + /// <param name="disposing"><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 (dispose) + if (_disposed) + { + return; + } + + if (disposing) { Stop(); } + + _disposed = true; } } @@ -627,9 +629,10 @@ namespace Emby.Server.Implementations.IO _monitor = monitor; } - public void Run() + public Task RunAsync() { _monitor.Start(); + return Task.CompletedTask; } public void Dispose() diff --git a/Emby.Server.Implementations/IStartupOptions.cs b/Emby.Server.Implementations/IStartupOptions.cs new file mode 100644 index 000000000..24aaa76c0 --- /dev/null +++ b/Emby.Server.Implementations/IStartupOptions.cs @@ -0,0 +1,40 @@ +namespace Emby.Server.Implementations +{ + public interface IStartupOptions + { + /// <summary> + /// --ffmpeg + /// </summary> + string FFmpegPath { get; } + + /// <summary> + /// --ffprobe + /// </summary> + string FFprobePath { get; } + + /// <summary> + /// --service + /// </summary> + bool IsService { get; } + + /// <summary> + /// --noautorunwebapp + /// </summary> + bool NoAutoRunWebApp { get; } + + /// <summary> + /// --package-name + /// </summary> + string PackageName { get; } + + /// <summary> + /// --restartpath + /// </summary> + string RestartPath { get; } + + /// <summary> + /// --restartargs + /// </summary> + string RestartArgs { get; } + } +} diff --git a/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs b/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs index 9705d54c9..109c21f18 100644 --- a/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs +++ b/Emby.Server.Implementations/Images/BaseDynamicImageProvider.cs @@ -215,7 +215,7 @@ namespace Emby.Server.Implementations.Images { return CreateSquareCollage(item, itemsWithImages, outputPath); } - if (item is Playlist || item is MusicGenre || item is Genre || item is GameGenre || item is PhotoAlbum) + if (item is Playlist || item is MusicGenre || item is Genre || item is PhotoAlbum) { return CreateSquareCollage(item, itemsWithImages, outputPath); } diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index f96a211ec..064006ebd 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -512,7 +512,7 @@ namespace Emby.Server.Implementations.Library if (forceCaseInsensitive || !ConfigurationManager.Configuration.EnableCaseSensitiveItemIds) { - key = key.ToLower(); + key = key.ToLowerInvariant(); } key = type.FullName + key; @@ -869,11 +869,6 @@ namespace Emby.Server.Implementations.Library return GetItemByNameId<MusicGenre>(MusicGenre.GetPath, name); } - public Guid GetGameGenreId(string name) - { - return GetItemByNameId<GameGenre>(GameGenre.GetPath, name); - } - /// <summary> /// Gets a Genre /// </summary> @@ -895,16 +890,6 @@ namespace Emby.Server.Implementations.Library } /// <summary> - /// Gets the game genre. - /// </summary> - /// <param name="name">The name.</param> - /// <returns>Task{GameGenre}.</returns> - public GameGenre GetGameGenre(string name) - { - return CreateItemByName<GameGenre>(GameGenre.GetPath, name, new DtoOptions(true)); - } - - /// <summary> /// Gets a Year /// </summary> /// <param name="value">The value.</param> @@ -1370,17 +1355,6 @@ namespace Emby.Server.Implementations.Library return ItemRepository.GetGenres(query); } - public QueryResult<Tuple<BaseItem, ItemCounts>> GetGameGenres(InternalItemsQuery query) - { - if (query.User != null) - { - AddUserToQuery(query, query.User); - } - - SetTopParentOrAncestorIds(query); - return ItemRepository.GetGameGenres(query); - } - public QueryResult<Tuple<BaseItem, ItemCounts>> GetMusicGenres(InternalItemsQuery query) { if (query.User != null) diff --git a/Emby.Server.Implementations/Library/MediaSourceManager.cs b/Emby.Server.Implementations/Library/MediaSourceManager.cs index b83fb9b39..24ab8e761 100644 --- a/Emby.Server.Implementations/Library/MediaSourceManager.cs +++ b/Emby.Server.Implementations/Library/MediaSourceManager.cs @@ -20,7 +20,6 @@ using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.Threading; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Library @@ -36,7 +35,6 @@ namespace Emby.Server.Implementations.Library private IMediaSourceProvider[] _providers; private readonly ILogger _logger; private readonly IUserDataManager _userDataManager; - private readonly ITimerFactory _timerFactory; private readonly Func<IMediaEncoder> _mediaEncoder; private ILocalizationManager _localizationManager; private IApplicationPaths _appPaths; @@ -51,7 +49,6 @@ namespace Emby.Server.Implementations.Library IJsonSerializer jsonSerializer, IFileSystem fileSystem, IUserDataManager userDataManager, - ITimerFactory timerFactory, Func<IMediaEncoder> mediaEncoder) { _itemRepo = itemRepo; @@ -61,7 +58,6 @@ namespace Emby.Server.Implementations.Library _jsonSerializer = jsonSerializer; _fileSystem = fileSystem; _userDataManager = userDataManager; - _timerFactory = timerFactory; _mediaEncoder = mediaEncoder; _localizationManager = localizationManager; _appPaths = applicationPaths; @@ -322,18 +318,18 @@ namespace Emby.Server.Implementations.Library private string[] NormalizeLanguage(string language) { - if (language != null) + if (language == null) { - var culture = _localizationManager.FindLanguageInfo(language); - if (culture != null) - { - return culture.ThreeLetterISOLanguageNames; - } + return Array.Empty<string>(); + } - return new string[] { language }; + var culture = _localizationManager.FindLanguageInfo(language); + if (culture != null) + { + return culture.ThreeLetterISOLanguageNames; } - return Array.Empty<string>(); + return new string[] { language }; } private void SetDefaultSubtitleStreamIndex(MediaSourceInfo source, UserItemData userData, User user, bool allowRememberingSelection) diff --git a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs index 9de766767..a3298c580 100644 --- a/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/PhotoResolver.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using MediaBrowser.Controller.Drawing; @@ -85,7 +86,7 @@ namespace Emby.Server.Implementations.Library.Resolvers return false; } - private static readonly string[] IgnoreFiles = + private static readonly HashSet<string> IgnoreFiles = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "folder", "thumb", @@ -102,7 +103,7 @@ namespace Emby.Server.Implementations.Library.Resolvers { var filename = Path.GetFileNameWithoutExtension(path) ?? string.Empty; - if (IgnoreFiles.Contains(filename, StringComparer.OrdinalIgnoreCase)) + if (IgnoreFiles.Contains(filename)) { return false; } @@ -112,7 +113,7 @@ namespace Emby.Server.Implementations.Library.Resolvers return false; } - return imageProcessor.SupportedInputFormats.Contains((Path.GetExtension(path) ?? string.Empty).TrimStart('.'), StringComparer.OrdinalIgnoreCase); + return imageProcessor.SupportedInputFormats.Contains((Path.GetExtension(path) ?? string.Empty).TrimStart('.')); } } diff --git a/Emby.Server.Implementations/Library/SearchEngine.cs b/Emby.Server.Implementations/Library/SearchEngine.cs index 71638b197..9c7f7dfcb 100644 --- a/Emby.Server.Implementations/Library/SearchEngine.cs +++ b/Emby.Server.Implementations/Library/SearchEngine.cs @@ -99,14 +99,12 @@ namespace Emby.Server.Implementations.Library if (!query.IncludeMedia) { AddIfMissing(includeItemTypes, typeof(Genre).Name); - AddIfMissing(includeItemTypes, typeof(GameGenre).Name); AddIfMissing(includeItemTypes, typeof(MusicGenre).Name); } } else { AddIfMissing(excludeItemTypes, typeof(Genre).Name); - AddIfMissing(excludeItemTypes, typeof(GameGenre).Name); AddIfMissing(excludeItemTypes, typeof(MusicGenre).Name); } diff --git a/Emby.Server.Implementations/Library/UserManager.cs b/Emby.Server.Implementations/Library/UserManager.cs index 70639dad5..40eda52c6 100644 --- a/Emby.Server.Implementations/Library/UserManager.cs +++ b/Emby.Server.Implementations/Library/UserManager.cs @@ -24,7 +24,6 @@ using MediaBrowser.Controller.Providers; using MediaBrowser.Controller.Security; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Connect; using MediaBrowser.Model.Cryptography; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; @@ -212,11 +211,8 @@ namespace Emby.Server.Implementations.Library { foreach (var user in users) { - if (!user.ConnectLinkType.HasValue || user.ConnectLinkType.Value == UserLinkType.LinkedUser) - { - user.Policy.IsAdministrator = true; - UpdateUserPolicy(user, user.Policy, false); - } + user.Policy.IsAdministrator = true; + UpdateUserPolicy(user, user.Policy, false); } } } @@ -272,13 +268,9 @@ namespace Emby.Server.Implementations.Library if (user != null) { - // Authenticate using local credentials if not a guest - if (!user.ConnectLinkType.HasValue || user.ConnectLinkType.Value != UserLinkType.Guest) - { - var authResult = await AuthenticateLocalUser(username, password, hashedPassword, user, remoteEndPoint).ConfigureAwait(false); - authenticationProvider = authResult.Item1; - success = authResult.Item2; - } + var authResult = await AuthenticateLocalUser(username, password, hashedPassword, user, remoteEndPoint).ConfigureAwait(false); + authenticationProvider = authResult.Item1; + success = authResult.Item2; } else { @@ -455,30 +447,30 @@ namespace Emby.Server.Implementations.Library private void UpdateInvalidLoginAttemptCount(User user, int newValue) { - if (user.Policy.InvalidLoginAttemptCount != newValue || newValue > 0) + if (user.Policy.InvalidLoginAttemptCount == newValue || newValue <= 0) { - user.Policy.InvalidLoginAttemptCount = newValue; + return; + } - var maxCount = user.Policy.IsAdministrator ? 3 : 5; + user.Policy.InvalidLoginAttemptCount = newValue; - // TODO: Fix - /* - var fireLockout = false; + var maxCount = user.Policy.IsAdministrator ? 3 : 5; - if (newValue >= maxCount) - { - _logger.LogDebug("Disabling user {0} due to {1} unsuccessful login attempts.", user.Name, newValue.ToString(CultureInfo.InvariantCulture)); - user.Policy.IsDisabled = true; + var fireLockout = false; - fireLockout = true; - }*/ + if (newValue >= maxCount) + { + _logger.LogDebug("Disabling user {0} due to {1} unsuccessful login attempts.", user.Name, newValue); + user.Policy.IsDisabled = true; - UpdateUserPolicy(user, user.Policy, false); + fireLockout = true; + } - /* if (fireLockout) - { - UserLockedOut?.Invoke(this, new GenericEventArgs<User>(user)); - }*/ + UpdateUserPolicy(user, user.Policy, false); + + if (fireLockout) + { + UserLockedOut?.Invoke(this, new GenericEventArgs<User>(user)); } } @@ -553,9 +545,6 @@ namespace Emby.Server.Implementations.Library LastActivityDate = user.LastActivityDate, LastLoginDate = user.LastLoginDate, Configuration = user.Configuration, - ConnectLinkType = user.ConnectLinkType, - ConnectUserId = user.ConnectUserId, - ConnectUserName = user.ConnectUserName, ServerId = _appHost.SystemId, Policy = user.Policy }; @@ -814,11 +803,6 @@ namespace Emby.Server.Implementations.Library throw new ArgumentNullException(nameof(user)); } - if (user.ConnectLinkType.HasValue && user.ConnectLinkType.Value == UserLinkType.Guest) - { - throw new ArgumentException("Passwords for guests cannot be changed."); - } - await GetAuthenticationProvider(user).ChangePassword(user, newPassword).ConfigureAwait(false); UpdateUser(user); @@ -925,11 +909,6 @@ namespace Emby.Server.Implementations.Library null : GetUserByName(enteredUsername); - if (user != null && user.ConnectLinkType.HasValue && user.ConnectLinkType.Value == UserLinkType.Guest) - { - throw new ArgumentException("Unable to process forgot password request for guests."); - } - var action = ForgotPasswordAction.InNetworkRequired; string pinFile = null; DateTime? expirationDate = null; @@ -974,10 +953,7 @@ namespace Emby.Server.Implementations.Library _lastPin = null; _lastPasswordPinCreationResult = null; - var users = Users.Where(i => !i.ConnectLinkType.HasValue || i.ConnectLinkType.Value != UserLinkType.Guest) - .ToList(); - - foreach (var user in users) + foreach (var user in Users) { await ResetPassword(user).ConfigureAwait(false); @@ -1205,9 +1181,11 @@ namespace Emby.Server.Implementations.Library _sessionManager = sessionManager; } - public void Run() + public Task RunAsync() { _userManager.UserPolicyUpdated += _userManager_UserPolicyUpdated; + + return Task.CompletedTask; } private void _userManager_UserPolicyUpdated(object sender, GenericEventArgs<User> e) diff --git a/Emby.Server.Implementations/Library/UserViewManager.cs b/Emby.Server.Implementations/Library/UserViewManager.cs index 9fa859bde..e9ce682ee 100644 --- a/Emby.Server.Implementations/Library/UserViewManager.cs +++ b/Emby.Server.Implementations/Library/UserViewManager.cs @@ -308,9 +308,6 @@ namespace Emby.Server.Implementations.Library mediaTypes.Add(MediaType.Book); mediaTypes.Add(MediaType.Audio); break; - case CollectionType.Games: - mediaTypes.Add(MediaType.Game); - break; case CollectionType.Music: mediaTypes.Add(MediaType.Audio); break; @@ -336,7 +333,6 @@ namespace Emby.Server.Implementations.Library typeof(Person).Name, typeof(Studio).Name, typeof(Year).Name, - typeof(GameGenre).Name, typeof(MusicGenre).Name, typeof(Genre).Name diff --git a/Emby.Server.Implementations/Library/Validators/GameGenresPostScanTask.cs b/Emby.Server.Implementations/Library/Validators/GameGenresPostScanTask.cs deleted file mode 100644 index 2b067951d..000000000 --- a/Emby.Server.Implementations/Library/Validators/GameGenresPostScanTask.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Persistence; -using Microsoft.Extensions.Logging; - -namespace Emby.Server.Implementations.Library.Validators -{ - /// <summary> - /// Class GameGenresPostScanTask - /// </summary> - public class GameGenresPostScanTask : ILibraryPostScanTask - { - /// <summary> - /// The _library manager - /// </summary> - private readonly ILibraryManager _libraryManager; - private readonly ILogger _logger; - private readonly IItemRepository _itemRepo; - - /// <summary> - /// Initializes a new instance of the <see cref="GameGenresPostScanTask" /> class. - /// </summary> - /// <param name="libraryManager">The library manager.</param> - /// <param name="logger">The logger.</param> - public GameGenresPostScanTask(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) - { - _libraryManager = libraryManager; - _logger = logger; - _itemRepo = itemRepo; - } - - /// <summary> - /// Runs the specified progress. - /// </summary> - /// <param name="progress">The progress.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public Task Run(IProgress<double> progress, CancellationToken cancellationToken) - { - return new GameGenresValidator(_libraryManager, _logger, _itemRepo).Run(progress, cancellationToken); - } - } -} diff --git a/Emby.Server.Implementations/Library/Validators/GameGenresValidator.cs b/Emby.Server.Implementations/Library/Validators/GameGenresValidator.cs deleted file mode 100644 index f5ffa1e45..000000000 --- a/Emby.Server.Implementations/Library/Validators/GameGenresValidator.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; -using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Persistence; -using Microsoft.Extensions.Logging; - -namespace Emby.Server.Implementations.Library.Validators -{ - class GameGenresValidator - { - /// <summary> - /// The _library manager - /// </summary> - private readonly ILibraryManager _libraryManager; - - /// <summary> - /// The _logger - /// </summary> - private readonly ILogger _logger; - private readonly IItemRepository _itemRepo; - - public GameGenresValidator(ILibraryManager libraryManager, ILogger logger, IItemRepository itemRepo) - { - _libraryManager = libraryManager; - _logger = logger; - _itemRepo = itemRepo; - } - - /// <summary> - /// Runs the specified progress. - /// </summary> - /// <param name="progress">The progress.</param> - /// <param name="cancellationToken">The cancellation token.</param> - /// <returns>Task.</returns> - public async Task Run(IProgress<double> progress, CancellationToken cancellationToken) - { - var names = _itemRepo.GetGameGenreNames(); - - var numComplete = 0; - var count = names.Count; - - foreach (var name in names) - { - try - { - var item = _libraryManager.GetGameGenre(name); - - await item.RefreshMetadata(cancellationToken).ConfigureAwait(false); - } - catch (OperationCanceledException) - { - // Don't clutter the log - throw; - } - catch (Exception ex) - { - _logger.LogError(ex, "Error refreshing {GenreName}", name); - } - - numComplete++; - double percent = numComplete; - percent /= count; - percent *= 100; - - progress.Report(percent); - } - - progress.Report(100); - } - } -} diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs index 6a2a46c9f..84ca130b7 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs @@ -35,8 +35,6 @@ using MediaBrowser.Model.Providers; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Reflection; using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.System; -using MediaBrowser.Model.Threading; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.LiveTv.EmbyTV @@ -65,7 +63,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV public static EmbyTV Current; - public event EventHandler DataSourceChanged; public event EventHandler<GenericEventArgs<TimerInfo>> TimerCreated; public event EventHandler<GenericEventArgs<string>> TimerCancelled; @@ -88,7 +85,6 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV ILibraryMonitor libraryMonitor, IProviderManager providerManager, IMediaEncoder mediaEncoder, - ITimerFactory timerFactory, IProcessFactory processFactory) { Current = this; @@ -110,7 +106,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _streamHelper = streamHelper; _seriesTimerProvider = new SeriesTimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "seriestimers")); - _timerProvider = new TimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "timers"), _logger, timerFactory); + _timerProvider = new TimerManager(fileSystem, jsonSerializer, _logger, Path.Combine(DataPath, "timers"), _logger); _timerProvider.TimerFired += _timerProvider_TimerFired; _config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated; @@ -124,7 +120,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } } - public async void Start() + public async Task Start() { _timerProvider.RestartTimers(); @@ -275,7 +271,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV foreach (var timer in seriesTimers) { - await UpdateTimersForSeriesTimer(timer, false, true).ConfigureAwait(false); + UpdateTimersForSeriesTimer(timer, false, true); } } @@ -763,12 +759,12 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _timerProvider.AddOrUpdate(timer, false); } - await UpdateTimersForSeriesTimer(info, true, false).ConfigureAwait(false); + UpdateTimersForSeriesTimer(info, true, false); return info.Id; } - public async Task UpdateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken) + public Task UpdateSeriesTimerAsync(SeriesTimerInfo info, CancellationToken cancellationToken) { var instance = _seriesTimerProvider.GetAll().FirstOrDefault(i => string.Equals(i.Id, info.Id, StringComparison.OrdinalIgnoreCase)); @@ -792,8 +788,10 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV _seriesTimerProvider.Update(instance); - await UpdateTimersForSeriesTimer(instance, true, true).ConfigureAwait(false); + UpdateTimersForSeriesTimer(instance, true, true); } + + return Task.CompletedTask; } public Task UpdateTimerAsync(TimerInfo updatedTimer, CancellationToken cancellationToken) @@ -2193,7 +2191,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV if (lockData) { - writer.WriteElementString("lockdata", true.ToString().ToLower()); + writer.WriteElementString("lockdata", true.ToString(CultureInfo.InvariantCulture).ToLowerInvariant()); } if (item.CriticRating.HasValue) @@ -2346,10 +2344,9 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV } } - private async Task UpdateTimersForSeriesTimer(SeriesTimerInfo seriesTimer, bool updateTimerSettings, bool deleteInvalidTimers) + private void UpdateTimersForSeriesTimer(SeriesTimerInfo seriesTimer, bool updateTimerSettings, bool deleteInvalidTimers) { - var allTimers = GetTimersForSeries(seriesTimer) - .ToList(); + var allTimers = GetTimersForSeries(seriesTimer).ToList(); var enabledTimersForSeries = new List<TimerInfo>(); diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs index 982a54b68..9c9ba09f5 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs @@ -1,12 +1,13 @@ +using System.Threading.Tasks; using MediaBrowser.Controller.Plugins; namespace Emby.Server.Implementations.LiveTv.EmbyTV { public class EntryPoint : IServerEntryPoint { - public void Run() + public Task RunAsync() { - EmbyTV.Current.Start(); + return EmbyTV.Current.Start(); } public void Dispose() diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs index 7f67d70a9..1dcb02f43 100644 --- a/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs +++ b/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs @@ -2,29 +2,27 @@ using System; using System.Collections.Concurrent; using System.Globalization; using System.Linq; +using System.Threading; using MediaBrowser.Controller.LiveTv; using MediaBrowser.Model.Events; using MediaBrowser.Model.IO; using MediaBrowser.Model.LiveTv; using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.Threading; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.LiveTv.EmbyTV { public class TimerManager : ItemDataProvider<TimerInfo> { - private readonly ConcurrentDictionary<string, ITimer> _timers = new ConcurrentDictionary<string, ITimer>(StringComparer.OrdinalIgnoreCase); + private readonly ConcurrentDictionary<string, Timer> _timers = new ConcurrentDictionary<string, Timer>(StringComparer.OrdinalIgnoreCase); private readonly ILogger _logger; public event EventHandler<GenericEventArgs<TimerInfo>> TimerFired; - private readonly ITimerFactory _timerFactory; - public TimerManager(IFileSystem fileSystem, IJsonSerializer jsonSerializer, ILogger logger, string dataPath, ILogger logger1, ITimerFactory timerFactory) + public TimerManager(IFileSystem fileSystem, IJsonSerializer jsonSerializer, ILogger logger, string dataPath, ILogger logger1) : base(fileSystem, jsonSerializer, logger, dataPath, (r1, r2) => string.Equals(r1.Id, r2.Id, StringComparison.OrdinalIgnoreCase)) { _logger = logger1; - _timerFactory = timerFactory; } public void RestartTimers() @@ -125,7 +123,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV private void StartTimer(TimerInfo item, TimeSpan dueTime) { - var timer = _timerFactory.Create(TimerCallback, item.Id, dueTime, TimeSpan.Zero); + var timer = new Timer(TimerCallback, item.Id, dueTime, TimeSpan.Zero); if (_timers.TryAdd(item.Id, timer)) { diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs index f152ac465..69b10e6da 100644 --- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs +++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs @@ -17,7 +17,7 @@ using MediaBrowser.Model.IO; using MediaBrowser.Model.LiveTv; using Microsoft.Extensions.Logging; -namespace Jellyfin.Server.Implementations.LiveTv.Listings +namespace Emby.Server.Implementations.LiveTv.Listings { public class XmlTvListingsProvider : IListingsProvider { diff --git a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs index 724e8afdf..1144c9ab1 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs @@ -399,7 +399,7 @@ namespace Emby.Server.Implementations.LiveTv { var name = serviceName + externalId + InternalVersionNumber; - return _libraryManager.GetNewItemId(name.ToLower(), typeof(LiveTvChannel)); + return _libraryManager.GetNewItemId(name.ToLowerInvariant(), typeof(LiveTvChannel)); } private const string ServiceName = "Emby"; @@ -407,21 +407,21 @@ namespace Emby.Server.Implementations.LiveTv { var name = ServiceName + externalId + InternalVersionNumber; - return name.ToLower().GetMD5().ToString("N"); + return name.ToLowerInvariant().GetMD5().ToString("N"); } public Guid GetInternalSeriesTimerId(string externalId) { var name = ServiceName + externalId + InternalVersionNumber; - return name.ToLower().GetMD5(); + return name.ToLowerInvariant().GetMD5(); } public Guid GetInternalProgramId(string externalId) { var name = ServiceName + externalId + InternalVersionNumber; - return _libraryManager.GetNewItemId(name.ToLower(), typeof(LiveTvProgram)); + return _libraryManager.GetNewItemId(name.ToLowerInvariant(), typeof(LiveTvProgram)); } public async Task<TimerInfo> GetTimerInfo(TimerInfoDto dto, bool isNew, LiveTvManager liveTv, CancellationToken cancellationToken) diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs index 575cb1c77..a36302876 100644 --- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs +++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs @@ -6,7 +6,6 @@ using System.Threading.Tasks; using Emby.Server.Implementations.Library; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Net; using MediaBrowser.Common.Progress; using MediaBrowser.Controller; using MediaBrowser.Controller.Channels; @@ -24,7 +23,6 @@ using MediaBrowser.Controller.Sorting; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Events; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; using MediaBrowser.Model.LiveTv; @@ -48,7 +46,6 @@ namespace Emby.Server.Implementations.LiveTv private readonly ILibraryManager _libraryManager; private readonly ITaskManager _taskManager; private readonly IJsonSerializer _jsonSerializer; - private readonly IProviderManager _providerManager; private readonly Func<IChannelManager> _channelManager; private readonly IDtoService _dtoService; @@ -56,7 +53,7 @@ namespace Emby.Server.Implementations.LiveTv private readonly LiveTvDtoService _tvDtoService; - private ILiveTvService[] _services = new ILiveTvService[] { }; + private ILiveTvService[] _services = Array.Empty<ILiveTvService>(); private ITunerHost[] _tunerHosts = Array.Empty<ITunerHost>(); private IListingsProvider[] _listingProviders = Array.Empty<IListingsProvider>(); @@ -85,7 +82,6 @@ namespace Emby.Server.Implementations.LiveTv ITaskManager taskManager, ILocalizationManager localization, IJsonSerializer jsonSerializer, - IProviderManager providerManager, IFileSystem fileSystem, Func<IChannelManager> channelManager) { @@ -97,7 +93,6 @@ namespace Emby.Server.Implementations.LiveTv _taskManager = taskManager; _localization = localization; _jsonSerializer = jsonSerializer; - _providerManager = providerManager; _fileSystem = fileSystem; _dtoService = dtoService; _userDataManager = userDataManager; @@ -132,8 +127,6 @@ namespace Emby.Server.Implementations.LiveTv foreach (var service in _services) { - service.DataSourceChanged += service_DataSourceChanged; - if (service is EmbyTV.EmbyTV embyTv) { embyTv.TimerCreated += EmbyTv_TimerCreated; @@ -189,14 +182,6 @@ namespace Emby.Server.Implementations.LiveTv return EmbyTV.EmbyTV.Current.DiscoverTuners(newDevicesOnly, cancellationToken); } - void service_DataSourceChanged(object sender, EventArgs e) - { - if (!_isDisposed) - { - _taskManager.CancelIfRunningAndQueue<RefreshChannelsScheduledTask>(); - } - } - public QueryResult<BaseItem> GetInternalChannels(LiveTvChannelQuery query, DtoOptions dtoOptions, CancellationToken cancellationToken) { var user = query.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(query.UserId); @@ -2158,17 +2143,28 @@ namespace Emby.Server.Implementations.LiveTv Dispose(true); } - private bool _isDisposed = false; + private bool _disposed = false; /// <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 dispose) { + if (_disposed) + { + return; + } + if (dispose) { - _isDisposed = true; + // TODO: Dispose stuff } + + _services = null; + _listingProviders = null; + _tunerHosts = null; + + _disposed = true; } private LiveTvServiceInfo[] GetServiceInfos() @@ -2469,7 +2465,8 @@ namespace Emby.Server.Implementations.LiveTv .Where(i => i != null) .Where(i => i.IsVisibleStandalone(user)) .SelectMany(i => _libraryManager.GetCollectionFolders(i)) - .DistinctBy(i => i.Id) + .GroupBy(x => x.Id) + .Select(x => x.First()) .OrderBy(i => i.SortName) .ToList(); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs index 716417ccb..4eff9252e 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs @@ -94,7 +94,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts var now = DateTime.UtcNow; - StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token); + var _ = StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token); //OpenedMediaSource.Protocol = MediaProtocol.File; //OpenedMediaSource.Path = tempFile; diff --git a/Emby.Server.Implementations/Localization/Core/ar.json b/Emby.Server.Implementations/Localization/Core/ar.json index ec2c3f237..eb145b4fe 100644 --- a/Emby.Server.Implementations/Localization/Core/ar.json +++ b/Emby.Server.Implementations/Localization/Core/ar.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "عملية تسجيل الدخول فشلت من {0}", "Favorites": "المفضلات", "Folders": "المجلدات", - "Games": "الألعاب", "Genres": "أنواع الأفلام", "HeaderAlbumArtists": "فنانو الألبومات", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "بدأ تشغيل المقطع الصوتي", "NotificationOptionAudioPlaybackStopped": "تم إيقاف تشغيل المقطع الصوتي", "NotificationOptionCameraImageUploaded": "تم رقع صورة الكاميرا", - "NotificationOptionGamePlayback": "تم تشغيل اللعبة", - "NotificationOptionGamePlaybackStopped": "تم إيقاف تشغيل اللعبة", "NotificationOptionInstallationFailed": "عملية التنصيب فشلت", "NotificationOptionNewLibraryContent": "تم إضافة محتوى جديد", "NotificationOptionPluginError": "فشل في الملحق", diff --git a/Emby.Server.Implementations/Localization/Core/bg-BG.json b/Emby.Server.Implementations/Localization/Core/bg-BG.json index ba6c98555..a71dc9346 100644 --- a/Emby.Server.Implementations/Localization/Core/bg-BG.json +++ b/Emby.Server.Implementations/Localization/Core/bg-BG.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", "Favorites": "Любими", "Folders": "Папки", - "Games": "Игри", "Genres": "Жанрове", "HeaderAlbumArtists": "Изпълнители на албуми", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Възпроизвеждането на звук започна", "NotificationOptionAudioPlaybackStopped": "Възпроизвеждането на звук е спряно", "NotificationOptionCameraImageUploaded": "Изображението от фотоапарата е качено", - "NotificationOptionGamePlayback": "Възпроизвеждането на играта започна", - "NotificationOptionGamePlaybackStopped": "Възпроизвеждането на играта е спряна", "NotificationOptionInstallationFailed": "Неуспешно инсталиране", "NotificationOptionNewLibraryContent": "Добавено е ново съдържание", "NotificationOptionPluginError": "Грешка в приставка", diff --git a/Emby.Server.Implementations/Localization/Core/ca.json b/Emby.Server.Implementations/Localization/Core/ca.json index a818b78de..74406a064 100644 --- a/Emby.Server.Implementations/Localization/Core/ca.json +++ b/Emby.Server.Implementations/Localization/Core/ca.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Intent de connexió fallit des de {0}", "Favorites": "Preferits", "Folders": "Directoris", - "Games": "Jocs", "Genres": "Gèneres", "HeaderAlbumArtists": "Album Artists", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Audio playback started", "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionPluginError": "Un component ha fallat", diff --git a/Emby.Server.Implementations/Localization/Core/cs.json b/Emby.Server.Implementations/Localization/Core/cs.json index e066051a8..a8b4a4424 100644 --- a/Emby.Server.Implementations/Localization/Core/cs.json +++ b/Emby.Server.Implementations/Localization/Core/cs.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Neúspěšný pokus o přihlášení z {0}", "Favorites": "Oblíbené", "Folders": "Složky", - "Games": "Hry", "Genres": "Žánry", "HeaderAlbumArtists": "Umělci alba", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Přehrávání audia zahájeno", "NotificationOptionAudioPlaybackStopped": "Přehrávání audia ukončeno", "NotificationOptionCameraImageUploaded": "Kamerový záznam nahrán", - "NotificationOptionGamePlayback": "Spuštění hry zahájeno", - "NotificationOptionGamePlaybackStopped": "Hra ukončena", "NotificationOptionInstallationFailed": "Chyba instalace", "NotificationOptionNewLibraryContent": "Přidán nový obsah", "NotificationOptionPluginError": "Chyba zásuvného modulu", diff --git a/Emby.Server.Implementations/Localization/Core/da.json b/Emby.Server.Implementations/Localization/Core/da.json index 30581c389..7004d44db 100644 --- a/Emby.Server.Implementations/Localization/Core/da.json +++ b/Emby.Server.Implementations/Localization/Core/da.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Fejlet loginforsøg fra {0}", "Favorites": "Favoritter", "Folders": "Mapper", - "Games": "Spil", "Genres": "Genre", "HeaderAlbumArtists": "Albumkunstnere", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Audioafspilning påbegyndt", "NotificationOptionAudioPlaybackStopped": "Audioafspilning stoppet", "NotificationOptionCameraImageUploaded": "Kamerabillede uploadet", - "NotificationOptionGamePlayback": "Afspilning af Spil påbegyndt", - "NotificationOptionGamePlaybackStopped": "Afspilning af Spil stoppet", "NotificationOptionInstallationFailed": "Installationsfejl", "NotificationOptionNewLibraryContent": "Nyt indhold tilføjet", "NotificationOptionPluginError": "Pluginfejl", diff --git a/Emby.Server.Implementations/Localization/Core/de.json b/Emby.Server.Implementations/Localization/Core/de.json index 98cb07663..7bd2e90fe 100644 --- a/Emby.Server.Implementations/Localization/Core/de.json +++ b/Emby.Server.Implementations/Localization/Core/de.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Fehlgeschlagener Anmeldeversuch von {0}", "Favorites": "Favoriten", "Folders": "Verzeichnisse", - "Games": "Spiele", "Genres": "Genres", "HeaderAlbumArtists": "Album-Künstler", "HeaderCameraUploads": "Kamera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Audiowiedergabe gestartet", "NotificationOptionAudioPlaybackStopped": "Audiowiedergabe gestoppt", "NotificationOptionCameraImageUploaded": "Kamera Bild hochgeladen", - "NotificationOptionGamePlayback": "Spielwiedergabe gestartet", - "NotificationOptionGamePlaybackStopped": "Spielwiedergabe gestoppt", "NotificationOptionInstallationFailed": "Installationsfehler", "NotificationOptionNewLibraryContent": "Neuer Inhalt hinzugefügt", "NotificationOptionPluginError": "Plugin Fehler", diff --git a/Emby.Server.Implementations/Localization/Core/el.json b/Emby.Server.Implementations/Localization/Core/el.json index ba687a089..91ca34edc 100644 --- a/Emby.Server.Implementations/Localization/Core/el.json +++ b/Emby.Server.Implementations/Localization/Core/el.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Αποτυχημένη προσπάθεια σύνδεσης από {0}", "Favorites": "Αγαπημένα", "Folders": "Φάκελοι", - "Games": "Παιχνίδια", "Genres": "Είδη", "HeaderAlbumArtists": "Άλμπουμ Καλλιτεχνών", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Η αναπαραγωγή ήχου ξεκίνησε", "NotificationOptionAudioPlaybackStopped": "Η αναπαραγωγή ήχου σταμάτησε", "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionGamePlayback": "Η αναπαραγωγή του παιχνιδιού ξεκίνησε", - "NotificationOptionGamePlaybackStopped": "Η αναπαραγωγή του παιχνιδιού σταμάτησε", "NotificationOptionInstallationFailed": "Αποτυχία εγκατάστασης", "NotificationOptionNewLibraryContent": "Προστέθηκε νέο περιεχόμενο", "NotificationOptionPluginError": "Αποτυχία του plugin", diff --git a/Emby.Server.Implementations/Localization/Core/en-GB.json b/Emby.Server.Implementations/Localization/Core/en-GB.json index 20d397a1a..332902292 100644 --- a/Emby.Server.Implementations/Localization/Core/en-GB.json +++ b/Emby.Server.Implementations/Localization/Core/en-GB.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", "Favorites": "Favourites", "Folders": "Folders", - "Games": "Games", "Genres": "Genres", "HeaderAlbumArtists": "Album Artists", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Audio playback started", "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionPluginError": "Plugin failure", diff --git a/Emby.Server.Implementations/Localization/Core/en-US.json b/Emby.Server.Implementations/Localization/Core/en-US.json index 69c8bf03c..f19cd532b 100644 --- a/Emby.Server.Implementations/Localization/Core/en-US.json +++ b/Emby.Server.Implementations/Localization/Core/en-US.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", "Favorites": "Favorites", "Folders": "Folders", - "Games": "Games", "Genres": "Genres", "HeaderAlbumArtists": "Album Artists", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Audio playback started", "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionPluginError": "Plugin failure", diff --git a/Emby.Server.Implementations/Localization/Core/es-AR.json b/Emby.Server.Implementations/Localization/Core/es-AR.json index aaaf09788..c01bb0c50 100644 --- a/Emby.Server.Implementations/Localization/Core/es-AR.json +++ b/Emby.Server.Implementations/Localization/Core/es-AR.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", "Favorites": "Favorites", "Folders": "Folders", - "Games": "Games", "Genres": "Genres", "HeaderAlbumArtists": "Album Artists", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Audio playback started", "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionPluginError": "Plugin failure", diff --git a/Emby.Server.Implementations/Localization/Core/es-MX.json b/Emby.Server.Implementations/Localization/Core/es-MX.json index 2ba9c8c7a..2285f2808 100644 --- a/Emby.Server.Implementations/Localization/Core/es-MX.json +++ b/Emby.Server.Implementations/Localization/Core/es-MX.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Intento fallido de inicio de sesión de {0}", "Favorites": "Favoritos", "Folders": "Carpetas", - "Games": "Juegos", "Genres": "Géneros", "HeaderAlbumArtists": "Artistas del Álbum", "HeaderCameraUploads": "Subidos desde Camara", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Reproducción de audio iniciada", "NotificationOptionAudioPlaybackStopped": "Reproducción de audio detenida", "NotificationOptionCameraImageUploaded": "Imagen de la cámara subida", - "NotificationOptionGamePlayback": "Ejecución de juego iniciada", - "NotificationOptionGamePlaybackStopped": "Ejecución de juego detenida", "NotificationOptionInstallationFailed": "Falla de instalación", "NotificationOptionNewLibraryContent": "Nuevo contenido agregado", "NotificationOptionPluginError": "Falla de complemento", diff --git a/Emby.Server.Implementations/Localization/Core/es.json b/Emby.Server.Implementations/Localization/Core/es.json index 38a282382..5d118d21f 100644 --- a/Emby.Server.Implementations/Localization/Core/es.json +++ b/Emby.Server.Implementations/Localization/Core/es.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Error al intentar iniciar sesión a partir de {0}", "Favorites": "Favoritos", "Folders": "Carpetas", - "Games": "Juegos", "Genres": "Géneros", "HeaderAlbumArtists": "Artistas del Álbum", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Se inició la reproducción de audio", "NotificationOptionAudioPlaybackStopped": "Se detuvo la reproducción de audio", "NotificationOptionCameraImageUploaded": "Imagen de la cámara cargada", - "NotificationOptionGamePlayback": "Se inició la reproducción del juego", - "NotificationOptionGamePlaybackStopped": "Se detuvo la reproducción del juego", "NotificationOptionInstallationFailed": "Error de instalación", "NotificationOptionNewLibraryContent": "Nuevo contenido añadido", "NotificationOptionPluginError": "Error en plugin", diff --git a/Emby.Server.Implementations/Localization/Core/fa.json b/Emby.Server.Implementations/Localization/Core/fa.json index 1d7bc5fe8..0a0c7553b 100644 --- a/Emby.Server.Implementations/Localization/Core/fa.json +++ b/Emby.Server.Implementations/Localization/Core/fa.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "تلاش برای ورود از {0} ناموفق بود", "Favorites": "مورد علاقه ها", "Folders": "پوشه ها", - "Games": "بازی ها", "Genres": "ژانرها", "HeaderAlbumArtists": "هنرمندان آلبوم", "HeaderCameraUploads": "آپلودهای دوربین", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "پخش صدا آغاز شد", "NotificationOptionAudioPlaybackStopped": "پخش صدا متوقف شد", "NotificationOptionCameraImageUploaded": "تصاویر دوربین آپلود شد", - "NotificationOptionGamePlayback": "پخش بازی آغاز شد", - "NotificationOptionGamePlaybackStopped": "پخش بازی متوقف شد", "NotificationOptionInstallationFailed": "شکست نصب", "NotificationOptionNewLibraryContent": "محتوای جدید افزوده شد", "NotificationOptionPluginError": "خرابی افزونه", diff --git a/Emby.Server.Implementations/Localization/Core/fr-CA.json b/Emby.Server.Implementations/Localization/Core/fr-CA.json index 22cd4cf6d..7202be9f5 100644 --- a/Emby.Server.Implementations/Localization/Core/fr-CA.json +++ b/Emby.Server.Implementations/Localization/Core/fr-CA.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", "Favorites": "Favorites", "Folders": "Folders", - "Games": "Games", "Genres": "Genres", "HeaderAlbumArtists": "Album Artists", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Audio playback started", "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionPluginError": "Plugin failure", diff --git a/Emby.Server.Implementations/Localization/Core/fr.json b/Emby.Server.Implementations/Localization/Core/fr.json index 085e22cf7..aa9a1add3 100644 --- a/Emby.Server.Implementations/Localization/Core/fr.json +++ b/Emby.Server.Implementations/Localization/Core/fr.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Échec d'une tentative de connexion de {0}", "Favorites": "Favoris", "Folders": "Dossiers", - "Games": "Jeux", "Genres": "Genres", "HeaderAlbumArtists": "Artistes de l'album", "HeaderCameraUploads": "Photos transférées", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Lecture audio démarrée", "NotificationOptionAudioPlaybackStopped": "Lecture audio arrêtée", "NotificationOptionCameraImageUploaded": "L'image de l'appareil photo a été transférée", - "NotificationOptionGamePlayback": "Lecture de jeu démarrée", - "NotificationOptionGamePlaybackStopped": "Lecture de jeu arrêtée", "NotificationOptionInstallationFailed": "Échec d'installation", "NotificationOptionNewLibraryContent": "Nouveau contenu ajouté", "NotificationOptionPluginError": "Erreur d'extension", diff --git a/Emby.Server.Implementations/Localization/Core/gsw.json b/Emby.Server.Implementations/Localization/Core/gsw.json index 537fe35d5..728002a56 100644 --- a/Emby.Server.Implementations/Localization/Core/gsw.json +++ b/Emby.Server.Implementations/Localization/Core/gsw.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", "Favorites": "Favorites", "Folders": "Folders", - "Games": "Spiel", "Genres": "Genres", "HeaderAlbumArtists": "Albuminterprete", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Audio playback started", "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionPluginError": "Plugin failure", diff --git a/Emby.Server.Implementations/Localization/Core/he.json b/Emby.Server.Implementations/Localization/Core/he.json index 6fff9d0ab..fff1d1f0e 100644 --- a/Emby.Server.Implementations/Localization/Core/he.json +++ b/Emby.Server.Implementations/Localization/Core/he.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", "Favorites": "Favorites", "Folders": "Folders", - "Games": "משחקים", "Genres": "ז'אנרים", "HeaderAlbumArtists": "Album Artists", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Audio playback started", "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionPluginError": "Plugin failure", diff --git a/Emby.Server.Implementations/Localization/Core/hr.json b/Emby.Server.Implementations/Localization/Core/hr.json index 3232a4ff7..f284b3cd9 100644 --- a/Emby.Server.Implementations/Localization/Core/hr.json +++ b/Emby.Server.Implementations/Localization/Core/hr.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Neuspjeli pokušaj prijave za {0}", "Favorites": "Omiljeni", "Folders": "Mape", - "Games": "Igre", "Genres": "Žanrovi", "HeaderAlbumArtists": "Izvođači albuma", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Reprodukcija glazbe započeta", "NotificationOptionAudioPlaybackStopped": "Reprodukcija audiozapisa je zaustavljena", "NotificationOptionCameraImageUploaded": "Slike kamere preuzete", - "NotificationOptionGamePlayback": "Igrica pokrenuta", - "NotificationOptionGamePlaybackStopped": "Reprodukcija igre je zaustavljena", "NotificationOptionInstallationFailed": "Instalacija nije izvršena", "NotificationOptionNewLibraryContent": "Novi sadržaj je dodan", "NotificationOptionPluginError": "Dodatak otkazao", diff --git a/Emby.Server.Implementations/Localization/Core/hu.json b/Emby.Server.Implementations/Localization/Core/hu.json index 3a0119faf..d2d16b18f 100644 --- a/Emby.Server.Implementations/Localization/Core/hu.json +++ b/Emby.Server.Implementations/Localization/Core/hu.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", "Favorites": "Kedvencek", "Folders": "Könyvtárak", - "Games": "Játékok", "Genres": "Műfajok", "HeaderAlbumArtists": "Album Előadók", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Audió lejátszás elkezdve", "NotificationOptionAudioPlaybackStopped": "Audió lejátszás befejezve", "NotificationOptionCameraImageUploaded": "Kamera kép feltöltve", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", "NotificationOptionInstallationFailed": "Telepítési hiba", "NotificationOptionNewLibraryContent": "Új tartalom hozzáadva", "NotificationOptionPluginError": "Bővítmény hiba", diff --git a/Emby.Server.Implementations/Localization/Core/it.json b/Emby.Server.Implementations/Localization/Core/it.json index 58b7bb61a..b3d9c16cf 100644 --- a/Emby.Server.Implementations/Localization/Core/it.json +++ b/Emby.Server.Implementations/Localization/Core/it.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Tentativo di accesso fallito da {0}", "Favorites": "Preferiti", "Folders": "Cartelle", - "Games": "Giochi", "Genres": "Generi", "HeaderAlbumArtists": "Artisti Album", "HeaderCameraUploads": "Caricamenti Fotocamera", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "La riproduzione audio è iniziata", "NotificationOptionAudioPlaybackStopped": "La riproduzione audio è stata interrotta", "NotificationOptionCameraImageUploaded": "Immagine fotocamera caricata", - "NotificationOptionGamePlayback": "Il gioco è stato avviato", - "NotificationOptionGamePlaybackStopped": "Il gioco è stato fermato", "NotificationOptionInstallationFailed": "Installazione fallita", "NotificationOptionNewLibraryContent": "Nuovo contenuto aggiunto", "NotificationOptionPluginError": "Errore del Plug-in", diff --git a/Emby.Server.Implementations/Localization/Core/kk.json b/Emby.Server.Implementations/Localization/Core/kk.json index 45b8617f1..ae256f79d 100644 --- a/Emby.Server.Implementations/Localization/Core/kk.json +++ b/Emby.Server.Implementations/Localization/Core/kk.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "{0} тарапынан кіру әрекеті сәтсіз", "Favorites": "Таңдаулылар", "Folders": "Қалталар", - "Games": "Ойындар", "Genres": "Жанрлар", "HeaderAlbumArtists": "Альбом орындаушылары", "HeaderCameraUploads": "Камерадан жүктелгендер", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Дыбыс ойнатуы басталды", "NotificationOptionAudioPlaybackStopped": "Дыбыс ойнатуы тоқтатылды", "NotificationOptionCameraImageUploaded": "Камерадан фотосурет кері қотарылған", - "NotificationOptionGamePlayback": "Ойын ойнатуы басталды", - "NotificationOptionGamePlaybackStopped": "Ойын ойнатуы тоқтатылды", "NotificationOptionInstallationFailed": "Орнату сәтсіздігі", "NotificationOptionNewLibraryContent": "Жаңа мазмұн үстелген", "NotificationOptionPluginError": "Плагин сәтсіздігі", diff --git a/Emby.Server.Implementations/Localization/Core/ko.json b/Emby.Server.Implementations/Localization/Core/ko.json index 04fc52d6e..21808fd18 100644 --- a/Emby.Server.Implementations/Localization/Core/ko.json +++ b/Emby.Server.Implementations/Localization/Core/ko.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", "Favorites": "Favorites", "Folders": "Folders", - "Games": "Games", "Genres": "Genres", "HeaderAlbumArtists": "앨범 아티스트", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Audio playback started", "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionPluginError": "Plugin failure", diff --git a/Emby.Server.Implementations/Localization/Core/lt-LT.json b/Emby.Server.Implementations/Localization/Core/lt-LT.json index 653565db6..558904f06 100644 --- a/Emby.Server.Implementations/Localization/Core/lt-LT.json +++ b/Emby.Server.Implementations/Localization/Core/lt-LT.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", "Favorites": "Favorites", "Folders": "Folders", - "Games": "Games", "Genres": "Žanrai", "HeaderAlbumArtists": "Album Artists", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Audio playback started", "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionPluginError": "Plugin failure", diff --git a/Emby.Server.Implementations/Localization/Core/ms.json b/Emby.Server.Implementations/Localization/Core/ms.json index aaaf09788..c01bb0c50 100644 --- a/Emby.Server.Implementations/Localization/Core/ms.json +++ b/Emby.Server.Implementations/Localization/Core/ms.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", "Favorites": "Favorites", "Folders": "Folders", - "Games": "Games", "Genres": "Genres", "HeaderAlbumArtists": "Album Artists", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Audio playback started", "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionPluginError": "Plugin failure", diff --git a/Emby.Server.Implementations/Localization/Core/nb.json b/Emby.Server.Implementations/Localization/Core/nb.json index ed63aa29c..dbda794ad 100644 --- a/Emby.Server.Implementations/Localization/Core/nb.json +++ b/Emby.Server.Implementations/Localization/Core/nb.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Mislykket påloggingsforsøk fra {0}", "Favorites": "Favoritter", "Folders": "Mapper", - "Games": "Spill", "Genres": "Sjanger", "HeaderAlbumArtists": "Albumartist", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Lyd tilbakespilling startet", "NotificationOptionAudioPlaybackStopped": "Lyd avspilling stoppet", "NotificationOptionCameraImageUploaded": "Kamera bilde lastet opp", - "NotificationOptionGamePlayback": "Spill avspillingen startet", - "NotificationOptionGamePlaybackStopped": "Filmer", "NotificationOptionInstallationFailed": "Installasjon feil", "NotificationOptionNewLibraryContent": "Ny innhold er lagt til", "NotificationOptionPluginError": "Plugin feil", diff --git a/Emby.Server.Implementations/Localization/Core/nl.json b/Emby.Server.Implementations/Localization/Core/nl.json index 7b8c8765e..589753c44 100644 --- a/Emby.Server.Implementations/Localization/Core/nl.json +++ b/Emby.Server.Implementations/Localization/Core/nl.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Mislukte aanmeld poging van {0}", "Favorites": "Favorieten", "Folders": "Mappen", - "Games": "Spellen", "Genres": "Genres", "HeaderAlbumArtists": "Album artiesten", "HeaderCameraUploads": "Camera uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Geluid gestart", "NotificationOptionAudioPlaybackStopped": "Geluid gestopt", "NotificationOptionCameraImageUploaded": "Camera afbeelding geüpload", - "NotificationOptionGamePlayback": "Spel gestart", - "NotificationOptionGamePlaybackStopped": "Spel gestopt", "NotificationOptionInstallationFailed": "Installatie mislukt", "NotificationOptionNewLibraryContent": "Nieuwe content toegevoegd", "NotificationOptionPluginError": "Plug-in fout", diff --git a/Emby.Server.Implementations/Localization/Core/pl.json b/Emby.Server.Implementations/Localization/Core/pl.json index 5aefa740b..92b12409d 100644 --- a/Emby.Server.Implementations/Localization/Core/pl.json +++ b/Emby.Server.Implementations/Localization/Core/pl.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Próba logowania przez {0} zakończona niepowodzeniem", "Favorites": "Ulubione", "Folders": "Foldery", - "Games": "Gry", "Genres": "Gatunki", "HeaderAlbumArtists": "Wykonawcy albumów", "HeaderCameraUploads": "Przekazane obrazy", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Rozpoczęto odtwarzanie muzyki", "NotificationOptionAudioPlaybackStopped": "Odtwarzane dźwięku zatrzymane", "NotificationOptionCameraImageUploaded": "Przekazano obraz z urządzenia mobilnego", - "NotificationOptionGamePlayback": "Odtwarzanie gry rozpoczęte", - "NotificationOptionGamePlaybackStopped": "Odtwarzanie gry zatrzymane", "NotificationOptionInstallationFailed": "Niepowodzenie instalacji", "NotificationOptionNewLibraryContent": "Dodano nową zawartość", "NotificationOptionPluginError": "Awaria wtyczki", diff --git a/Emby.Server.Implementations/Localization/Core/pt-BR.json b/Emby.Server.Implementations/Localization/Core/pt-BR.json index 9ae25d3ac..aaedf0850 100644 --- a/Emby.Server.Implementations/Localization/Core/pt-BR.json +++ b/Emby.Server.Implementations/Localization/Core/pt-BR.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Falha na tentativa de login de {0}", "Favorites": "Favoritos", "Folders": "Pastas", - "Games": "Jogos", "Genres": "Gêneros", "HeaderAlbumArtists": "Artistas do Álbum", "HeaderCameraUploads": "Uploads da Câmera", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Reprodução de áudio iniciada", "NotificationOptionAudioPlaybackStopped": "Reprodução de áudio parada", "NotificationOptionCameraImageUploaded": "Imagem de câmera enviada", - "NotificationOptionGamePlayback": "Reprodução de jogo iniciada", - "NotificationOptionGamePlaybackStopped": "Reprodução de jogo parada", "NotificationOptionInstallationFailed": "Falha na instalação", "NotificationOptionNewLibraryContent": "Novo conteúdo adicionado", "NotificationOptionPluginError": "Falha de plugin", diff --git a/Emby.Server.Implementations/Localization/Core/pt-PT.json b/Emby.Server.Implementations/Localization/Core/pt-PT.json index 59c25f0e3..dc69d8af2 100644 --- a/Emby.Server.Implementations/Localization/Core/pt-PT.json +++ b/Emby.Server.Implementations/Localization/Core/pt-PT.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", "Favorites": "Favorites", "Folders": "Folders", - "Games": "Games", "Genres": "Genres", "HeaderAlbumArtists": "Album Artists", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Audio playback started", "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionPluginError": "Plugin failure", diff --git a/Emby.Server.Implementations/Localization/Core/ru.json b/Emby.Server.Implementations/Localization/Core/ru.json index 338141294..d799fa50b 100644 --- a/Emby.Server.Implementations/Localization/Core/ru.json +++ b/Emby.Server.Implementations/Localization/Core/ru.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "{0} - попытка входа неудачна", "Favorites": "Избранное", "Folders": "Папки", - "Games": "Игры", "Genres": "Жанры", "HeaderAlbumArtists": "Исп-ли альбома", "HeaderCameraUploads": "Камеры", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Воспр-ие аудио зап-но", "NotificationOptionAudioPlaybackStopped": "Восп-ие аудио ост-но", "NotificationOptionCameraImageUploaded": "Произведена выкладка отснятого с камеры", - "NotificationOptionGamePlayback": "Воспр-ие игры зап-но", - "NotificationOptionGamePlaybackStopped": "Восп-ие игры ост-но", "NotificationOptionInstallationFailed": "Сбой установки", "NotificationOptionNewLibraryContent": "Новое содержание добавлено", "NotificationOptionPluginError": "Сбой плагина", diff --git a/Emby.Server.Implementations/Localization/Core/sk.json b/Emby.Server.Implementations/Localization/Core/sk.json index ed0c68952..bc7e7184e 100644 --- a/Emby.Server.Implementations/Localization/Core/sk.json +++ b/Emby.Server.Implementations/Localization/Core/sk.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Neúspešný pokus o prihlásenie z {0}", "Favorites": "Obľúbené", "Folders": "Priečinky", - "Games": "Hry", "Genres": "Žánre", "HeaderAlbumArtists": "Album Artists", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Spustené prehrávanie audia", "NotificationOptionAudioPlaybackStopped": "Zastavené prehrávanie audia", "NotificationOptionCameraImageUploaded": "Nahraný obrázok z fotoaparátu", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionGamePlaybackStopped": "Hra ukončená", "NotificationOptionInstallationFailed": "Chyba inštalácie", "NotificationOptionNewLibraryContent": "Pridaný nový obsah", "NotificationOptionPluginError": "Chyba rozšírenia", diff --git a/Emby.Server.Implementations/Localization/Core/sl-SI.json b/Emby.Server.Implementations/Localization/Core/sl-SI.json index 8fe279836..e850257d4 100644 --- a/Emby.Server.Implementations/Localization/Core/sl-SI.json +++ b/Emby.Server.Implementations/Localization/Core/sl-SI.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", "Favorites": "Favorites", "Folders": "Folders", - "Games": "Games", "Genres": "Genres", "HeaderAlbumArtists": "Album Artists", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Audio playback started", "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionPluginError": "Plugin failure", diff --git a/Emby.Server.Implementations/Localization/Core/sv.json b/Emby.Server.Implementations/Localization/Core/sv.json index 517d648bb..fb2761a7d 100644 --- a/Emby.Server.Implementations/Localization/Core/sv.json +++ b/Emby.Server.Implementations/Localization/Core/sv.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Misslyckat inloggningsförsök från {0}", "Favorites": "Favoriter", "Folders": "Mappar", - "Games": "Spel", "Genres": "Genrer", "HeaderAlbumArtists": "Albumartister", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Ljuduppspelning har påbörjats", "NotificationOptionAudioPlaybackStopped": "Ljuduppspelning stoppad", "NotificationOptionCameraImageUploaded": "Kamerabild har laddats upp", - "NotificationOptionGamePlayback": "Spel har startats", - "NotificationOptionGamePlaybackStopped": "Spel stoppat", "NotificationOptionInstallationFailed": "Fel vid installation", "NotificationOptionNewLibraryContent": "Nytt innehåll har lagts till", "NotificationOptionPluginError": "Fel uppstod med tillägget", diff --git a/Emby.Server.Implementations/Localization/Core/tr.json b/Emby.Server.Implementations/Localization/Core/tr.json index 9e86e2125..495f82db6 100644 --- a/Emby.Server.Implementations/Localization/Core/tr.json +++ b/Emby.Server.Implementations/Localization/Core/tr.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", "Favorites": "Favorites", "Folders": "Folders", - "Games": "Games", "Genres": "Genres", "HeaderAlbumArtists": "Album Artists", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Audio playback started", "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionPluginError": "Plugin failure", diff --git a/Emby.Server.Implementations/Localization/Core/zh-CN.json b/Emby.Server.Implementations/Localization/Core/zh-CN.json index 6d877ec17..8910a6bce 100644 --- a/Emby.Server.Implementations/Localization/Core/zh-CN.json +++ b/Emby.Server.Implementations/Localization/Core/zh-CN.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "来自 {0} 的失败登入", "Favorites": "最爱", "Folders": "文件夹", - "Games": "游戏", "Genres": "风格", "HeaderAlbumArtists": "专辑作家", "HeaderCameraUploads": "相机上传", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "音频开始播放", "NotificationOptionAudioPlaybackStopped": "音频播放已停止", "NotificationOptionCameraImageUploaded": "相机图片已上传", - "NotificationOptionGamePlayback": "游戏开始", - "NotificationOptionGamePlaybackStopped": "游戏停止", "NotificationOptionInstallationFailed": "安装失败", "NotificationOptionNewLibraryContent": "已添加新内容", "NotificationOptionPluginError": "插件失败", diff --git a/Emby.Server.Implementations/Localization/Core/zh-HK.json b/Emby.Server.Implementations/Localization/Core/zh-HK.json index cad5700fd..387fc2b92 100644 --- a/Emby.Server.Implementations/Localization/Core/zh-HK.json +++ b/Emby.Server.Implementations/Localization/Core/zh-HK.json @@ -14,7 +14,6 @@ "FailedLoginAttemptWithUserName": "Failed login attempt from {0}", "Favorites": "Favorites", "Folders": "Folders", - "Games": "Games", "Genres": "Genres", "HeaderAlbumArtists": "Album Artists", "HeaderCameraUploads": "Camera Uploads", @@ -51,8 +50,6 @@ "NotificationOptionAudioPlayback": "Audio playback started", "NotificationOptionAudioPlaybackStopped": "Audio playback stopped", "NotificationOptionCameraImageUploaded": "Camera image uploaded", - "NotificationOptionGamePlayback": "Game playback started", - "NotificationOptionGamePlaybackStopped": "Game playback stopped", "NotificationOptionInstallationFailed": "Installation failure", "NotificationOptionNewLibraryContent": "New content added", "NotificationOptionPluginError": "Plugin failure", diff --git a/Emby.Server.Implementations/Localization/LocalizationManager.cs b/Emby.Server.Implementations/Localization/LocalizationManager.cs index 7af8cf18c..31217730b 100644 --- a/Emby.Server.Implementations/Localization/LocalizationManager.cs +++ b/Emby.Server.Implementations/Localization/LocalizationManager.cs @@ -4,12 +4,14 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; using MediaBrowser.Controller.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Extensions; using MediaBrowser.Model.Globalization; using MediaBrowser.Model.IO; -using MediaBrowser.Model.Reflection; using MediaBrowser.Model.Serialization; using Microsoft.Extensions.Logging; @@ -36,8 +38,7 @@ namespace Emby.Server.Implementations.Localization private readonly IFileSystem _fileSystem; private readonly IJsonSerializer _jsonSerializer; private readonly ILogger _logger; - private readonly IAssemblyInfo _assemblyInfo; - private readonly ITextLocalizer _textLocalizer; + private static readonly Assembly _assembly = typeof(LocalizationManager).Assembly; /// <summary> /// Initializes a new instance of the <see cref="LocalizationManager" /> class. @@ -49,67 +50,63 @@ namespace Emby.Server.Implementations.Localization IServerConfigurationManager configurationManager, IFileSystem fileSystem, IJsonSerializer jsonSerializer, - ILoggerFactory loggerFactory, - IAssemblyInfo assemblyInfo, - ITextLocalizer textLocalizer) + ILoggerFactory loggerFactory) { _configurationManager = configurationManager; _fileSystem = fileSystem; _jsonSerializer = jsonSerializer; _logger = loggerFactory.CreateLogger(nameof(LocalizationManager)); - _assemblyInfo = assemblyInfo; - _textLocalizer = textLocalizer; - - ExtractAll(); } - private void ExtractAll() + public async Task LoadAll() { - var type = GetType(); - var resourcePath = type.Namespace + ".Ratings."; - - var localizationPath = LocalizationPath; + const string ratingsResource = "Emby.Server.Implementations.Localization.Ratings."; - Directory.CreateDirectory(localizationPath); + Directory.CreateDirectory(LocalizationPath); - var existingFiles = GetRatingsFiles(localizationPath) - .Select(Path.GetFileName) - .ToList(); + var existingFiles = GetRatingsFiles(LocalizationPath).Select(Path.GetFileName); // Extract from the assembly - foreach (var resource in _assemblyInfo - .GetManifestResourceNames(type) - .Where(i => i.StartsWith(resourcePath))) + foreach (var resource in _assembly.GetManifestResourceNames()) { - var filename = "ratings-" + resource.Substring(resourcePath.Length); + if (!resource.StartsWith(ratingsResource)) + { + continue; + } + + string filename = "ratings-" + resource.Substring(ratingsResource.Length); - if (!existingFiles.Contains(filename)) + if (existingFiles.Contains(filename)) { - using (var stream = _assemblyInfo.GetManifestResourceStream(type, resource)) - { - var target = Path.Combine(localizationPath, filename); - _logger.LogInformation("Extracting ratings to {0}", target); + continue; + } - using (var fs = _fileSystem.GetFileStream(target, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) - { - stream.CopyTo(fs); - } + using (var stream = _assembly.GetManifestResourceStream(resource)) + { + string target = Path.Combine(LocalizationPath, filename); + _logger.LogInformation("Extracting ratings to {0}", target); + + using (var fs = _fileSystem.GetFileStream(target, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read)) + { + await stream.CopyToAsync(fs); } } } - foreach (var file in GetRatingsFiles(localizationPath)) + foreach (var file in GetRatingsFiles(LocalizationPath)) { - LoadRatings(file); + await LoadRatings(file); } LoadAdditionalRatings(); + + await LoadCultures(); } private void LoadAdditionalRatings() { - LoadRatings("au", new[] { - + LoadRatings("au", new[] + { new ParentalRating("AU-G", 1), new ParentalRating("AU-PG", 5), new ParentalRating("AU-M", 6), @@ -120,8 +117,8 @@ namespace Emby.Server.Implementations.Localization new ParentalRating("AU-RC", 11) }); - LoadRatings("be", new[] { - + LoadRatings("be", new[] + { new ParentalRating("BE-AL", 1), new ParentalRating("BE-MG6", 2), new ParentalRating("BE-6", 3), @@ -130,8 +127,8 @@ namespace Emby.Server.Implementations.Localization new ParentalRating("BE-16", 8) }); - LoadRatings("de", new[] { - + LoadRatings("de", new[] + { new ParentalRating("DE-0", 1), new ParentalRating("FSK-0", 1), new ParentalRating("DE-6", 5), @@ -144,8 +141,8 @@ namespace Emby.Server.Implementations.Localization new ParentalRating("FSK-18", 9) }); - LoadRatings("ru", new[] { - + LoadRatings("ru", new[] + { new ParentalRating("RU-0+", 1), new ParentalRating("RU-6+", 3), new ParentalRating("RU-12+", 7), @@ -159,29 +156,20 @@ namespace Emby.Server.Implementations.Localization _allParentalRatings[country] = ratings.ToDictionary(i => i.Name); } - private List<string> GetRatingsFiles(string directory) - { - return _fileSystem.GetFilePaths(directory, false) - .Where(i => string.Equals(Path.GetExtension(i), ".txt", StringComparison.OrdinalIgnoreCase)) - .Where(i => Path.GetFileName(i).StartsWith("ratings-", StringComparison.OrdinalIgnoreCase)) - .ToList(); - } + private IEnumerable<string> GetRatingsFiles(string directory) + => _fileSystem.GetFilePaths(directory, false) + .Where(i => string.Equals(Path.GetExtension(i), ".csv", StringComparison.OrdinalIgnoreCase)) + .Where(i => Path.GetFileName(i).StartsWith("ratings-", StringComparison.OrdinalIgnoreCase)); /// <summary> /// Gets the localization path. /// </summary> /// <value>The localization path.</value> - public string LocalizationPath => Path.Combine(_configurationManager.ApplicationPaths.ProgramDataPath, "localization"); - - public string RemoveDiacritics(string text) - { - return _textLocalizer.RemoveDiacritics(text); - } + public string LocalizationPath + => Path.Combine(_configurationManager.ApplicationPaths.ProgramDataPath, "localization"); public string NormalizeFormKD(string text) - { - return _textLocalizer.NormalizeFormKD(text); - } + => text.Normalize(NormalizationForm.FormKD); private CultureDto[] _cultures; @@ -190,90 +178,88 @@ namespace Emby.Server.Implementations.Localization /// </summary> /// <returns>IEnumerable{CultureDto}.</returns> public CultureDto[] GetCultures() - { - var result = _cultures; - if (result != null) - { - return result; - } + => _cultures; - var type = GetType(); - var path = type.Namespace + ".iso6392.txt"; + private async Task LoadCultures() + { + List<CultureDto> list = new List<CultureDto>(); - var list = new List<CultureDto>(); + const string path = "Emby.Server.Implementations.Localization.iso6392.txt"; - using (var stream = _assemblyInfo.GetManifestResourceStream(type, path)) + using (var stream = _assembly.GetManifestResourceStream(path)) + using (var reader = new StreamReader(stream)) { - using (var reader = new StreamReader(stream)) + while (!reader.EndOfStream) { - while (!reader.EndOfStream) + var line = await reader.ReadLineAsync(); + + if (string.IsNullOrWhiteSpace(line)) { - var line = reader.ReadLine(); + continue; + } + + var parts = line.Split('|'); + + if (parts.Length == 5) + { + string name = parts[3]; + if (string.IsNullOrWhiteSpace(name)) + { + continue; + } - if (!string.IsNullOrWhiteSpace(line)) + string twoCharName = parts[2]; + if (string.IsNullOrWhiteSpace(twoCharName)) + { + continue; + } + + string[] threeletterNames; + if (string.IsNullOrWhiteSpace(parts[1])) + { + threeletterNames = new [] { parts[0] }; + } + else { - var parts = line.Split('|'); - - if (parts.Length == 5) - { - var threeletterNames = new List<string> { parts[0] }; - if (!string.IsNullOrWhiteSpace(parts[1])) - { - threeletterNames.Add(parts[1]); - } - - list.Add(new CultureDto - { - DisplayName = parts[3], - Name = parts[3], - ThreeLetterISOLanguageNames = threeletterNames.ToArray(), - TwoLetterISOLanguageName = parts[2] - }); - } + threeletterNames = new [] { parts[0], parts[1] }; } + + list.Add(new CultureDto + { + DisplayName = name, + Name = name, + ThreeLetterISOLanguageNames = threeletterNames, + TwoLetterISOLanguageName = twoCharName + }); } } } - result = list.Where(i => !string.IsNullOrWhiteSpace(i.Name) && - !string.IsNullOrWhiteSpace(i.DisplayName) && - i.ThreeLetterISOLanguageNames.Length > 0 && - !string.IsNullOrWhiteSpace(i.TwoLetterISOLanguageName)).ToArray(); - - _cultures = result; - - return result; + _cultures = list.ToArray(); } public CultureDto FindLanguageInfo(string language) - { - return GetCultures() - .FirstOrDefault(i => string.Equals(i.DisplayName, language, StringComparison.OrdinalIgnoreCase) || - string.Equals(i.Name, language, StringComparison.OrdinalIgnoreCase) || - i.ThreeLetterISOLanguageNames.Contains(language, StringComparer.OrdinalIgnoreCase) || - string.Equals(i.TwoLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase)); - } + => GetCultures() + .FirstOrDefault(i => + string.Equals(i.DisplayName, language, StringComparison.OrdinalIgnoreCase) + || string.Equals(i.Name, language, StringComparison.OrdinalIgnoreCase) + || i.ThreeLetterISOLanguageNames.Contains(language, StringComparer.OrdinalIgnoreCase) + || string.Equals(i.TwoLetterISOLanguageName, language, StringComparison.OrdinalIgnoreCase)); /// <summary> /// Gets the countries. /// </summary> /// <returns>IEnumerable{CountryInfo}.</returns> - public CountryInfo[] GetCountries() - { - // ToDo: DeserializeFromStream seems broken in this case - string jsonCountries = "[{\"Name\":\"AF\",\"DisplayName\":\"Afghanistan\",\"TwoLetterISORegionName\":\"AF\",\"ThreeLetterISORegionName\":\"AFG\"},{\"Name\":\"AL\",\"DisplayName\":\"Albania\",\"TwoLetterISORegionName\":\"AL\",\"ThreeLetterISORegionName\":\"ALB\"},{\"Name\":\"DZ\",\"DisplayName\":\"Algeria\",\"TwoLetterISORegionName\":\"DZ\",\"ThreeLetterISORegionName\":\"DZA\"},{\"Name\":\"AR\",\"DisplayName\":\"Argentina\",\"TwoLetterISORegionName\":\"AR\",\"ThreeLetterISORegionName\":\"ARG\"},{\"Name\":\"AM\",\"DisplayName\":\"Armenia\",\"TwoLetterISORegionName\":\"AM\",\"ThreeLetterISORegionName\":\"ARM\"},{\"Name\":\"AU\",\"DisplayName\":\"Australia\",\"TwoLetterISORegionName\":\"AU\",\"ThreeLetterISORegionName\":\"AUS\"},{\"Name\":\"AT\",\"DisplayName\":\"Austria\",\"TwoLetterISORegionName\":\"AT\",\"ThreeLetterISORegionName\":\"AUT\"},{\"Name\":\"AZ\",\"DisplayName\":\"Azerbaijan\",\"TwoLetterISORegionName\":\"AZ\",\"ThreeLetterISORegionName\":\"AZE\"},{\"Name\":\"BH\",\"DisplayName\":\"Bahrain\",\"TwoLetterISORegionName\":\"BH\",\"ThreeLetterISORegionName\":\"BHR\"},{\"Name\":\"BD\",\"DisplayName\":\"Bangladesh\",\"TwoLetterISORegionName\":\"BD\",\"ThreeLetterISORegionName\":\"BGD\"},{\"Name\":\"BY\",\"DisplayName\":\"Belarus\",\"TwoLetterISORegionName\":\"BY\",\"ThreeLetterISORegionName\":\"BLR\"},{\"Name\":\"BE\",\"DisplayName\":\"Belgium\",\"TwoLetterISORegionName\":\"BE\",\"ThreeLetterISORegionName\":\"BEL\"},{\"Name\":\"BZ\",\"DisplayName\":\"Belize\",\"TwoLetterISORegionName\":\"BZ\",\"ThreeLetterISORegionName\":\"BLZ\"},{\"Name\":\"VE\",\"DisplayName\":\"Bolivarian Republic of Venezuela\",\"TwoLetterISORegionName\":\"VE\",\"ThreeLetterISORegionName\":\"VEN\"},{\"Name\":\"BO\",\"DisplayName\":\"Bolivia\",\"TwoLetterISORegionName\":\"BO\",\"ThreeLetterISORegionName\":\"BOL\"},{\"Name\":\"BA\",\"DisplayName\":\"Bosnia and Herzegovina\",\"TwoLetterISORegionName\":\"BA\",\"ThreeLetterISORegionName\":\"BIH\"},{\"Name\":\"BW\",\"DisplayName\":\"Botswana\",\"TwoLetterISORegionName\":\"BW\",\"ThreeLetterISORegionName\":\"BWA\"},{\"Name\":\"BR\",\"DisplayName\":\"Brazil\",\"TwoLetterISORegionName\":\"BR\",\"ThreeLetterISORegionName\":\"BRA\"},{\"Name\":\"BN\",\"DisplayName\":\"Brunei Darussalam\",\"TwoLetterISORegionName\":\"BN\",\"ThreeLetterISORegionName\":\"BRN\"},{\"Name\":\"BG\",\"DisplayName\":\"Bulgaria\",\"TwoLetterISORegionName\":\"BG\",\"ThreeLetterISORegionName\":\"BGR\"},{\"Name\":\"KH\",\"DisplayName\":\"Cambodia\",\"TwoLetterISORegionName\":\"KH\",\"ThreeLetterISORegionName\":\"KHM\"},{\"Name\":\"CM\",\"DisplayName\":\"Cameroon\",\"TwoLetterISORegionName\":\"CM\",\"ThreeLetterISORegionName\":\"CMR\"},{\"Name\":\"CA\",\"DisplayName\":\"Canada\",\"TwoLetterISORegionName\":\"CA\",\"ThreeLetterISORegionName\":\"CAN\"},{\"Name\":\"029\",\"DisplayName\":\"Caribbean\",\"TwoLetterISORegionName\":\"029\",\"ThreeLetterISORegionName\":\"029\"},{\"Name\":\"CL\",\"DisplayName\":\"Chile\",\"TwoLetterISORegionName\":\"CL\",\"ThreeLetterISORegionName\":\"CHL\"},{\"Name\":\"CO\",\"DisplayName\":\"Colombia\",\"TwoLetterISORegionName\":\"CO\",\"ThreeLetterISORegionName\":\"COL\"},{\"Name\":\"CD\",\"DisplayName\":\"Congo [DRC]\",\"TwoLetterISORegionName\":\"CD\",\"ThreeLetterISORegionName\":\"COD\"},{\"Name\":\"CR\",\"DisplayName\":\"Costa Rica\",\"TwoLetterISORegionName\":\"CR\",\"ThreeLetterISORegionName\":\"CRI\"},{\"Name\":\"HR\",\"DisplayName\":\"Croatia\",\"TwoLetterISORegionName\":\"HR\",\"ThreeLetterISORegionName\":\"HRV\"},{\"Name\":\"CZ\",\"DisplayName\":\"Czech Republic\",\"TwoLetterISORegionName\":\"CZ\",\"ThreeLetterISORegionName\":\"CZE\"},{\"Name\":\"DK\",\"DisplayName\":\"Denmark\",\"TwoLetterISORegionName\":\"DK\",\"ThreeLetterISORegionName\":\"DNK\"},{\"Name\":\"DO\",\"DisplayName\":\"Dominican Republic\",\"TwoLetterISORegionName\":\"DO\",\"ThreeLetterISORegionName\":\"DOM\"},{\"Name\":\"EC\",\"DisplayName\":\"Ecuador\",\"TwoLetterISORegionName\":\"EC\",\"ThreeLetterISORegionName\":\"ECU\"},{\"Name\":\"EG\",\"DisplayName\":\"Egypt\",\"TwoLetterISORegionName\":\"EG\",\"ThreeLetterISORegionName\":\"EGY\"},{\"Name\":\"SV\",\"DisplayName\":\"El Salvador\",\"TwoLetterISORegionName\":\"SV\",\"ThreeLetterISORegionName\":\"SLV\"},{\"Name\":\"ER\",\"DisplayName\":\"Eritrea\",\"TwoLetterISORegionName\":\"ER\",\"ThreeLetterISORegionName\":\"ERI\"},{\"Name\":\"EE\",\"DisplayName\":\"Estonia\",\"TwoLetterISORegionName\":\"EE\",\"ThreeLetterISORegionName\":\"EST\"},{\"Name\":\"ET\",\"DisplayName\":\"Ethiopia\",\"TwoLetterISORegionName\":\"ET\",\"ThreeLetterISORegionName\":\"ETH\"},{\"Name\":\"FO\",\"DisplayName\":\"Faroe Islands\",\"TwoLetterISORegionName\":\"FO\",\"ThreeLetterISORegionName\":\"FRO\"},{\"Name\":\"FI\",\"DisplayName\":\"Finland\",\"TwoLetterISORegionName\":\"FI\",\"ThreeLetterISORegionName\":\"FIN\"},{\"Name\":\"FR\",\"DisplayName\":\"France\",\"TwoLetterISORegionName\":\"FR\",\"ThreeLetterISORegionName\":\"FRA\"},{\"Name\":\"GE\",\"DisplayName\":\"Georgia\",\"TwoLetterISORegionName\":\"GE\",\"ThreeLetterISORegionName\":\"GEO\"},{\"Name\":\"DE\",\"DisplayName\":\"Germany\",\"TwoLetterISORegionName\":\"DE\",\"ThreeLetterISORegionName\":\"DEU\"},{\"Name\":\"GR\",\"DisplayName\":\"Greece\",\"TwoLetterISORegionName\":\"GR\",\"ThreeLetterISORegionName\":\"GRC\"},{\"Name\":\"GL\",\"DisplayName\":\"Greenland\",\"TwoLetterISORegionName\":\"GL\",\"ThreeLetterISORegionName\":\"GRL\"},{\"Name\":\"GT\",\"DisplayName\":\"Guatemala\",\"TwoLetterISORegionName\":\"GT\",\"ThreeLetterISORegionName\":\"GTM\"},{\"Name\":\"HT\",\"DisplayName\":\"Haiti\",\"TwoLetterISORegionName\":\"HT\",\"ThreeLetterISORegionName\":\"HTI\"},{\"Name\":\"HN\",\"DisplayName\":\"Honduras\",\"TwoLetterISORegionName\":\"HN\",\"ThreeLetterISORegionName\":\"HND\"},{\"Name\":\"HK\",\"DisplayName\":\"Hong Kong S.A.R.\",\"TwoLetterISORegionName\":\"HK\",\"ThreeLetterISORegionName\":\"HKG\"},{\"Name\":\"HU\",\"DisplayName\":\"Hungary\",\"TwoLetterISORegionName\":\"HU\",\"ThreeLetterISORegionName\":\"HUN\"},{\"Name\":\"IS\",\"DisplayName\":\"Iceland\",\"TwoLetterISORegionName\":\"IS\",\"ThreeLetterISORegionName\":\"ISL\"},{\"Name\":\"IN\",\"DisplayName\":\"India\",\"TwoLetterISORegionName\":\"IN\",\"ThreeLetterISORegionName\":\"IND\"},{\"Name\":\"ID\",\"DisplayName\":\"Indonesia\",\"TwoLetterISORegionName\":\"ID\",\"ThreeLetterISORegionName\":\"IDN\"},{\"Name\":\"IR\",\"DisplayName\":\"Iran\",\"TwoLetterISORegionName\":\"IR\",\"ThreeLetterISORegionName\":\"IRN\"},{\"Name\":\"IQ\",\"DisplayName\":\"Iraq\",\"TwoLetterISORegionName\":\"IQ\",\"ThreeLetterISORegionName\":\"IRQ\"},{\"Name\":\"IE\",\"DisplayName\":\"Ireland\",\"TwoLetterISORegionName\":\"IE\",\"ThreeLetterISORegionName\":\"IRL\"},{\"Name\":\"PK\",\"DisplayName\":\"Islamic Republic of Pakistan\",\"TwoLetterISORegionName\":\"PK\",\"ThreeLetterISORegionName\":\"PAK\"},{\"Name\":\"IL\",\"DisplayName\":\"Israel\",\"TwoLetterISORegionName\":\"IL\",\"ThreeLetterISORegionName\":\"ISR\"},{\"Name\":\"IT\",\"DisplayName\":\"Italy\",\"TwoLetterISORegionName\":\"IT\",\"ThreeLetterISORegionName\":\"ITA\"},{\"Name\":\"CI\",\"DisplayName\":\"Ivory Coast\",\"TwoLetterISORegionName\":\"CI\",\"ThreeLetterISORegionName\":\"CIV\"},{\"Name\":\"JM\",\"DisplayName\":\"Jamaica\",\"TwoLetterISORegionName\":\"JM\",\"ThreeLetterISORegionName\":\"JAM\"},{\"Name\":\"JP\",\"DisplayName\":\"Japan\",\"TwoLetterISORegionName\":\"JP\",\"ThreeLetterISORegionName\":\"JPN\"},{\"Name\":\"JO\",\"DisplayName\":\"Jordan\",\"TwoLetterISORegionName\":\"JO\",\"ThreeLetterISORegionName\":\"JOR\"},{\"Name\":\"KZ\",\"DisplayName\":\"Kazakhstan\",\"TwoLetterISORegionName\":\"KZ\",\"ThreeLetterISORegionName\":\"KAZ\"},{\"Name\":\"KE\",\"DisplayName\":\"Kenya\",\"TwoLetterISORegionName\":\"KE\",\"ThreeLetterISORegionName\":\"KEN\"},{\"Name\":\"KR\",\"DisplayName\":\"Korea\",\"TwoLetterISORegionName\":\"KR\",\"ThreeLetterISORegionName\":\"KOR\"},{\"Name\":\"KW\",\"DisplayName\":\"Kuwait\",\"TwoLetterISORegionName\":\"KW\",\"ThreeLetterISORegionName\":\"KWT\"},{\"Name\":\"KG\",\"DisplayName\":\"Kyrgyzstan\",\"TwoLetterISORegionName\":\"KG\",\"ThreeLetterISORegionName\":\"KGZ\"},{\"Name\":\"LA\",\"DisplayName\":\"Lao P.D.R.\",\"TwoLetterISORegionName\":\"LA\",\"ThreeLetterISORegionName\":\"LAO\"},{\"Name\":\"419\",\"DisplayName\":\"Latin America\",\"TwoLetterISORegionName\":\"419\",\"ThreeLetterISORegionName\":\"419\"},{\"Name\":\"LV\",\"DisplayName\":\"Latvia\",\"TwoLetterISORegionName\":\"LV\",\"ThreeLetterISORegionName\":\"LVA\"},{\"Name\":\"LB\",\"DisplayName\":\"Lebanon\",\"TwoLetterISORegionName\":\"LB\",\"ThreeLetterISORegionName\":\"LBN\"},{\"Name\":\"LY\",\"DisplayName\":\"Libya\",\"TwoLetterISORegionName\":\"LY\",\"ThreeLetterISORegionName\":\"LBY\"},{\"Name\":\"LI\",\"DisplayName\":\"Liechtenstein\",\"TwoLetterISORegionName\":\"LI\",\"ThreeLetterISORegionName\":\"LIE\"},{\"Name\":\"LT\",\"DisplayName\":\"Lithuania\",\"TwoLetterISORegionName\":\"LT\",\"ThreeLetterISORegionName\":\"LTU\"},{\"Name\":\"LU\",\"DisplayName\":\"Luxembourg\",\"TwoLetterISORegionName\":\"LU\",\"ThreeLetterISORegionName\":\"LUX\"},{\"Name\":\"MO\",\"DisplayName\":\"Macao S.A.R.\",\"TwoLetterISORegionName\":\"MO\",\"ThreeLetterISORegionName\":\"MAC\"},{\"Name\":\"MK\",\"DisplayName\":\"Macedonia (FYROM)\",\"TwoLetterISORegionName\":\"MK\",\"ThreeLetterISORegionName\":\"MKD\"},{\"Name\":\"MY\",\"DisplayName\":\"Malaysia\",\"TwoLetterISORegionName\":\"MY\",\"ThreeLetterISORegionName\":\"MYS\"},{\"Name\":\"MV\",\"DisplayName\":\"Maldives\",\"TwoLetterISORegionName\":\"MV\",\"ThreeLetterISORegionName\":\"MDV\"},{\"Name\":\"ML\",\"DisplayName\":\"Mali\",\"TwoLetterISORegionName\":\"ML\",\"ThreeLetterISORegionName\":\"MLI\"},{\"Name\":\"MT\",\"DisplayName\":\"Malta\",\"TwoLetterISORegionName\":\"MT\",\"ThreeLetterISORegionName\":\"MLT\"},{\"Name\":\"MX\",\"DisplayName\":\"Mexico\",\"TwoLetterISORegionName\":\"MX\",\"ThreeLetterISORegionName\":\"MEX\"},{\"Name\":\"MN\",\"DisplayName\":\"Mongolia\",\"TwoLetterISORegionName\":\"MN\",\"ThreeLetterISORegionName\":\"MNG\"},{\"Name\":\"ME\",\"DisplayName\":\"Montenegro\",\"TwoLetterISORegionName\":\"ME\",\"ThreeLetterISORegionName\":\"MNE\"},{\"Name\":\"MA\",\"DisplayName\":\"Morocco\",\"TwoLetterISORegionName\":\"MA\",\"ThreeLetterISORegionName\":\"MAR\"},{\"Name\":\"NP\",\"DisplayName\":\"Nepal\",\"TwoLetterISORegionName\":\"NP\",\"ThreeLetterISORegionName\":\"NPL\"},{\"Name\":\"NL\",\"DisplayName\":\"Netherlands\",\"TwoLetterISORegionName\":\"NL\",\"ThreeLetterISORegionName\":\"NLD\"},{\"Name\":\"NZ\",\"DisplayName\":\"New Zealand\",\"TwoLetterISORegionName\":\"NZ\",\"ThreeLetterISORegionName\":\"NZL\"},{\"Name\":\"NI\",\"DisplayName\":\"Nicaragua\",\"TwoLetterISORegionName\":\"NI\",\"ThreeLetterISORegionName\":\"NIC\"},{\"Name\":\"NG\",\"DisplayName\":\"Nigeria\",\"TwoLetterISORegionName\":\"NG\",\"ThreeLetterISORegionName\":\"NGA\"},{\"Name\":\"NO\",\"DisplayName\":\"Norway\",\"TwoLetterISORegionName\":\"NO\",\"ThreeLetterISORegionName\":\"NOR\"},{\"Name\":\"OM\",\"DisplayName\":\"Oman\",\"TwoLetterISORegionName\":\"OM\",\"ThreeLetterISORegionName\":\"OMN\"},{\"Name\":\"PA\",\"DisplayName\":\"Panama\",\"TwoLetterISORegionName\":\"PA\",\"ThreeLetterISORegionName\":\"PAN\"},{\"Name\":\"PY\",\"DisplayName\":\"Paraguay\",\"TwoLetterISORegionName\":\"PY\",\"ThreeLetterISORegionName\":\"PRY\"},{\"Name\":\"CN\",\"DisplayName\":\"People's Republic of China\",\"TwoLetterISORegionName\":\"CN\",\"ThreeLetterISORegionName\":\"CHN\"},{\"Name\":\"PE\",\"DisplayName\":\"Peru\",\"TwoLetterISORegionName\":\"PE\",\"ThreeLetterISORegionName\":\"PER\"},{\"Name\":\"PH\",\"DisplayName\":\"Philippines\",\"TwoLetterISORegionName\":\"PH\",\"ThreeLetterISORegionName\":\"PHL\"},{\"Name\":\"PL\",\"DisplayName\":\"Poland\",\"TwoLetterISORegionName\":\"PL\",\"ThreeLetterISORegionName\":\"POL\"},{\"Name\":\"PT\",\"DisplayName\":\"Portugal\",\"TwoLetterISORegionName\":\"PT\",\"ThreeLetterISORegionName\":\"PRT\"},{\"Name\":\"MC\",\"DisplayName\":\"Principality of Monaco\",\"TwoLetterISORegionName\":\"MC\",\"ThreeLetterISORegionName\":\"MCO\"},{\"Name\":\"PR\",\"DisplayName\":\"Puerto Rico\",\"TwoLetterISORegionName\":\"PR\",\"ThreeLetterISORegionName\":\"PRI\"},{\"Name\":\"QA\",\"DisplayName\":\"Qatar\",\"TwoLetterISORegionName\":\"QA\",\"ThreeLetterISORegionName\":\"QAT\"},{\"Name\":\"MD\",\"DisplayName\":\"Republica Moldova\",\"TwoLetterISORegionName\":\"MD\",\"ThreeLetterISORegionName\":\"MDA\"},{\"Name\":\"RE\",\"DisplayName\":\"Réunion\",\"TwoLetterISORegionName\":\"RE\",\"ThreeLetterISORegionName\":\"REU\"},{\"Name\":\"RO\",\"DisplayName\":\"Romania\",\"TwoLetterISORegionName\":\"RO\",\"ThreeLetterISORegionName\":\"ROU\"},{\"Name\":\"RU\",\"DisplayName\":\"Russia\",\"TwoLetterISORegionName\":\"RU\",\"ThreeLetterISORegionName\":\"RUS\"},{\"Name\":\"RW\",\"DisplayName\":\"Rwanda\",\"TwoLetterISORegionName\":\"RW\",\"ThreeLetterISORegionName\":\"RWA\"},{\"Name\":\"SA\",\"DisplayName\":\"Saudi Arabia\",\"TwoLetterISORegionName\":\"SA\",\"ThreeLetterISORegionName\":\"SAU\"},{\"Name\":\"SN\",\"DisplayName\":\"Senegal\",\"TwoLetterISORegionName\":\"SN\",\"ThreeLetterISORegionName\":\"SEN\"},{\"Name\":\"RS\",\"DisplayName\":\"Serbia\",\"TwoLetterISORegionName\":\"RS\",\"ThreeLetterISORegionName\":\"SRB\"},{\"Name\":\"CS\",\"DisplayName\":\"Serbia and Montenegro (Former)\",\"TwoLetterISORegionName\":\"CS\",\"ThreeLetterISORegionName\":\"SCG\"},{\"Name\":\"SG\",\"DisplayName\":\"Singapore\",\"TwoLetterISORegionName\":\"SG\",\"ThreeLetterISORegionName\":\"SGP\"},{\"Name\":\"SK\",\"DisplayName\":\"Slovakia\",\"TwoLetterISORegionName\":\"SK\",\"ThreeLetterISORegionName\":\"SVK\"},{\"Name\":\"SI\",\"DisplayName\":\"Slovenia\",\"TwoLetterISORegionName\":\"SI\",\"ThreeLetterISORegionName\":\"SVN\"},{\"Name\":\"SO\",\"DisplayName\":\"Soomaaliya\",\"TwoLetterISORegionName\":\"SO\",\"ThreeLetterISORegionName\":\"SOM\"},{\"Name\":\"ZA\",\"DisplayName\":\"South Africa\",\"TwoLetterISORegionName\":\"ZA\",\"ThreeLetterISORegionName\":\"ZAF\"},{\"Name\":\"ES\",\"DisplayName\":\"Spain\",\"TwoLetterISORegionName\":\"ES\",\"ThreeLetterISORegionName\":\"ESP\"},{\"Name\":\"LK\",\"DisplayName\":\"Sri Lanka\",\"TwoLetterISORegionName\":\"LK\",\"ThreeLetterISORegionName\":\"LKA\"},{\"Name\":\"SE\",\"DisplayName\":\"Sweden\",\"TwoLetterISORegionName\":\"SE\",\"ThreeLetterISORegionName\":\"SWE\"},{\"Name\":\"CH\",\"DisplayName\":\"Switzerland\",\"TwoLetterISORegionName\":\"CH\",\"ThreeLetterISORegionName\":\"CHE\"},{\"Name\":\"SY\",\"DisplayName\":\"Syria\",\"TwoLetterISORegionName\":\"SY\",\"ThreeLetterISORegionName\":\"SYR\"},{\"Name\":\"TW\",\"DisplayName\":\"Taiwan\",\"TwoLetterISORegionName\":\"TW\",\"ThreeLetterISORegionName\":\"TWN\"},{\"Name\":\"TJ\",\"DisplayName\":\"Tajikistan\",\"TwoLetterISORegionName\":\"TJ\",\"ThreeLetterISORegionName\":\"TAJ\"},{\"Name\":\"TH\",\"DisplayName\":\"Thailand\",\"TwoLetterISORegionName\":\"TH\",\"ThreeLetterISORegionName\":\"THA\"},{\"Name\":\"TT\",\"DisplayName\":\"Trinidad and Tobago\",\"TwoLetterISORegionName\":\"TT\",\"ThreeLetterISORegionName\":\"TTO\"},{\"Name\":\"TN\",\"DisplayName\":\"Tunisia\",\"TwoLetterISORegionName\":\"TN\",\"ThreeLetterISORegionName\":\"TUN\"},{\"Name\":\"TR\",\"DisplayName\":\"Turkey\",\"TwoLetterISORegionName\":\"TR\",\"ThreeLetterISORegionName\":\"TUR\"},{\"Name\":\"TM\",\"DisplayName\":\"Turkmenistan\",\"TwoLetterISORegionName\":\"TM\",\"ThreeLetterISORegionName\":\"TKM\"},{\"Name\":\"AE\",\"DisplayName\":\"U.A.E.\",\"TwoLetterISORegionName\":\"AE\",\"ThreeLetterISORegionName\":\"ARE\"},{\"Name\":\"UA\",\"DisplayName\":\"Ukraine\",\"TwoLetterISORegionName\":\"UA\",\"ThreeLetterISORegionName\":\"UKR\"},{\"Name\":\"GB\",\"DisplayName\":\"United Kingdom\",\"TwoLetterISORegionName\":\"GB\",\"ThreeLetterISORegionName\":\"GBR\"},{\"Name\":\"US\",\"DisplayName\":\"United States\",\"TwoLetterISORegionName\":\"US\",\"ThreeLetterISORegionName\":\"USA\"},{\"Name\":\"UY\",\"DisplayName\":\"Uruguay\",\"TwoLetterISORegionName\":\"UY\",\"ThreeLetterISORegionName\":\"URY\"},{\"Name\":\"UZ\",\"DisplayName\":\"Uzbekistan\",\"TwoLetterISORegionName\":\"UZ\",\"ThreeLetterISORegionName\":\"UZB\"},{\"Name\":\"VN\",\"DisplayName\":\"Vietnam\",\"TwoLetterISORegionName\":\"VN\",\"ThreeLetterISORegionName\":\"VNM\"},{\"Name\":\"YE\",\"DisplayName\":\"Yemen\",\"TwoLetterISORegionName\":\"YE\",\"ThreeLetterISORegionName\":\"YEM\"},{\"Name\":\"ZW\",\"DisplayName\":\"Zimbabwe\",\"TwoLetterISORegionName\":\"ZW\",\"ThreeLetterISORegionName\":\"ZWE\"}]"; - - return _jsonSerializer.DeserializeFromString<CountryInfo[]>(jsonCountries); - } + public Task<CountryInfo[]> GetCountries() + => _jsonSerializer.DeserializeFromStreamAsync<CountryInfo[]>( + _assembly.GetManifestResourceStream("Emby.Server.Implementations.Localization.countries.json")); /// <summary> /// Gets the parental ratings. /// </summary> /// <returns>IEnumerable{ParentalRating}.</returns> - public ParentalRating[] GetParentalRatings() - { - return GetParentalRatingsDictionary().Values.ToArray(); - } + public IEnumerable<ParentalRating> GetParentalRatings() + => GetParentalRatingsDictionary().Values; /// <summary> /// Gets the parental ratings dictionary. @@ -288,14 +274,7 @@ namespace Emby.Server.Implementations.Localization countryCode = "us"; } - var ratings = GetRatings(countryCode); - - if (ratings == null) - { - ratings = GetRatings("us"); - } - - return ratings; + return GetRatings(countryCode) ?? GetRatings("us"); } /// <summary> @@ -314,37 +293,43 @@ namespace Emby.Server.Implementations.Localization /// </summary> /// <param name="file">The file.</param> /// <returns>Dictionary{System.StringParentalRating}.</returns> - private void LoadRatings(string file) + private async Task LoadRatings(string file) { - var dict = File.ReadAllLines(file).Select(i => + Dictionary<string, ParentalRating> dict + = new Dictionary<string, ParentalRating>(StringComparer.OrdinalIgnoreCase); + + using (var str = File.OpenRead(file)) + using (var reader = new StreamReader(str)) { - if (!string.IsNullOrWhiteSpace(i)) + string line; + while ((line = await reader.ReadLineAsync()) != null) { - var parts = i.Split(','); + if (string.IsNullOrWhiteSpace(line)) + { + continue; + } - if (parts.Length == 2) + string[] parts = line.Split(','); + if (parts.Length == 2 + && int.TryParse(parts[1], NumberStyles.Integer, UsCulture, out var value)) { - if (int.TryParse(parts[1], NumberStyles.Integer, UsCulture, out var value)) - { - return new ParentalRating { Name = parts[0], Value = value }; - } + dict.Add(parts[0], (new ParentalRating { Name = parts[0], Value = value })); } +#if DEBUG + else + { + _logger.LogWarning("Misformed line in {Path}", file); + } +#endif } + } - return null; - - }) - .Where(i => i != null) - .ToDictionary(i => i.Name, StringComparer.OrdinalIgnoreCase); - - var countryCode = Path.GetFileNameWithoutExtension(file) - .Split('-') - .Last(); + var countryCode = Path.GetFileNameWithoutExtension(file).Split('-')[1]; _allParentalRatings[countryCode] = dict; } - private readonly string[] _unratedValues = { "n/a", "unrated", "not rated" }; + private static readonly string[] _unratedValues = { "n/a", "unrated", "not rated" }; /// <summary> /// Gets the rating level. @@ -435,7 +420,7 @@ namespace Emby.Server.Implementations.Localization return phrase; } - const string DefaultCulture = "en-US"; + private const string DefaultCulture = "en-US"; private readonly ConcurrentDictionary<string, Dictionary<string, string>> _dictionaries = new ConcurrentDictionary<string, Dictionary<string, string>>(StringComparer.OrdinalIgnoreCase); @@ -450,10 +435,11 @@ namespace Emby.Server.Implementations.Localization const string prefix = "Core"; var key = prefix + culture; - return _dictionaries.GetOrAdd(key, k => GetDictionary(prefix, culture, DefaultCulture + ".json")); + return _dictionaries.GetOrAdd(key, + f => GetDictionary(prefix, culture, DefaultCulture + ".json").GetAwaiter().GetResult()); } - private Dictionary<string, string> GetDictionary(string prefix, string culture, string baseFilename) + private async Task<Dictionary<string, string>> GetDictionary(string prefix, string culture, string baseFilename) { if (string.IsNullOrEmpty(culture)) { @@ -464,25 +450,30 @@ namespace Emby.Server.Implementations.Localization var namespaceName = GetType().Namespace + "." + prefix; - CopyInto(dictionary, namespaceName + "." + baseFilename); - CopyInto(dictionary, namespaceName + "." + GetResourceFilename(culture)); + await CopyInto(dictionary, namespaceName + "." + baseFilename); + await CopyInto(dictionary, namespaceName + "." + GetResourceFilename(culture)); return dictionary; } - private void CopyInto(IDictionary<string, string> dictionary, string resourcePath) + private async Task CopyInto(IDictionary<string, string> dictionary, string resourcePath) { - using (var stream = _assemblyInfo.GetManifestResourceStream(GetType(), resourcePath)) + using (var stream = _assembly.GetManifestResourceStream(resourcePath)) { + // If a Culture doesn't have a translation the stream will be null and it defaults to en-us further up the chain if (stream != null) { - var dict = _jsonSerializer.DeserializeFromStream<Dictionary<string, string>>(stream); + var dict = await _jsonSerializer.DeserializeFromStreamAsync<Dictionary<string, string>>(stream); foreach (var key in dict.Keys) { dictionary[key] = dict[key]; } } + else + { + _logger.LogError("Missing translation/culture resource: {ResourcePath}", resourcePath); + } } } @@ -492,11 +483,11 @@ namespace Emby.Server.Implementations.Localization if (parts.Length == 2) { - culture = parts[0].ToLower() + "-" + parts[1].ToUpper(); + culture = parts[0].ToLowerInvariant() + "-" + parts[1].ToUpperInvariant(); } else { - culture = culture.ToLower(); + culture = culture.ToLowerInvariant(); } return culture + ".json"; @@ -506,29 +497,23 @@ namespace Emby.Server.Implementations.Localization => new LocalizationOption[] { new LocalizationOption("Arabic", "ar"), - new LocalizationOption("Belarusian (Belarus)", "be-BY"), new LocalizationOption("Bulgarian (Bulgaria)", "bg-BG"), new LocalizationOption("Catalan", "ca"), new LocalizationOption("Chinese Simplified", "zh-CN"), new LocalizationOption("Chinese Traditional", "zh-TW"), - new LocalizationOption("Chinese Traditional (Hong Kong)", "zh-HK"), new LocalizationOption("Croatian", "hr"), new LocalizationOption("Czech", "cs"), new LocalizationOption("Danish", "da"), new LocalizationOption("Dutch", "nl"), new LocalizationOption("English (United Kingdom)", "en-GB"), new LocalizationOption("English (United States)", "en-US"), - new LocalizationOption("Finnish", "fi"), new LocalizationOption("French", "fr"), new LocalizationOption("French (Canada)", "fr-CA"), new LocalizationOption("German", "de"), new LocalizationOption("Greek", "el"), new LocalizationOption("Hebrew", "he"), - new LocalizationOption("Hindi (India)", "hi-IN"), new LocalizationOption("Hungarian", "hu"), - new LocalizationOption("Indonesian", "id"), new LocalizationOption("Italian", "it"), - new LocalizationOption("Japanese", "ja"), new LocalizationOption("Kazakh", "kk"), new LocalizationOption("Korean", "ko"), new LocalizationOption("Lithuanian", "lt-LT"), @@ -538,25 +523,15 @@ namespace Emby.Server.Implementations.Localization new LocalizationOption("Polish", "pl"), new LocalizationOption("Portuguese (Brazil)", "pt-BR"), new LocalizationOption("Portuguese (Portugal)", "pt-PT"), - new LocalizationOption("Romanian", "ro"), new LocalizationOption("Russian", "ru"), new LocalizationOption("Slovak", "sk"), new LocalizationOption("Slovenian (Slovenia)", "sl-SI"), new LocalizationOption("Spanish", "es"), - new LocalizationOption("Spanish (Latin America)", "es-419"), + new LocalizationOption("Spanish (Argentina)", "es-AR"), new LocalizationOption("Spanish (Mexico)", "es-MX"), new LocalizationOption("Swedish", "sv"), new LocalizationOption("Swiss German", "gsw"), - new LocalizationOption("Turkish", "tr"), - new LocalizationOption("Ukrainian", "uk"), - new LocalizationOption("Vietnamese", "vi") + new LocalizationOption("Turkish", "tr") }; } - - public interface ITextLocalizer - { - string RemoveDiacritics(string text); - - string NormalizeFormKD(string text); - } } diff --git a/Emby.Server.Implementations/Localization/Ratings/br.txt b/Emby.Server.Implementations/Localization/Ratings/br.csv index e5edaf62c..e5edaf62c 100644 --- a/Emby.Server.Implementations/Localization/Ratings/br.txt +++ b/Emby.Server.Implementations/Localization/Ratings/br.csv diff --git a/Emby.Server.Implementations/Localization/Ratings/ca.txt b/Emby.Server.Implementations/Localization/Ratings/ca.csv index 5aef0580f..5aef0580f 100644 --- a/Emby.Server.Implementations/Localization/Ratings/ca.txt +++ b/Emby.Server.Implementations/Localization/Ratings/ca.csv diff --git a/Emby.Server.Implementations/Localization/Ratings/co.txt b/Emby.Server.Implementations/Localization/Ratings/co.csv index 9684fa052..9684fa052 100644 --- a/Emby.Server.Implementations/Localization/Ratings/co.txt +++ b/Emby.Server.Implementations/Localization/Ratings/co.csv diff --git a/Emby.Server.Implementations/Localization/Ratings/dk.txt b/Emby.Server.Implementations/Localization/Ratings/dk.csv index 5364ae1f2..5364ae1f2 100644 --- a/Emby.Server.Implementations/Localization/Ratings/dk.txt +++ b/Emby.Server.Implementations/Localization/Ratings/dk.csv diff --git a/Emby.Server.Implementations/Localization/Ratings/es.txt b/Emby.Server.Implementations/Localization/Ratings/es.csv index 887d91ba6..887d91ba6 100644 --- a/Emby.Server.Implementations/Localization/Ratings/es.txt +++ b/Emby.Server.Implementations/Localization/Ratings/es.csv diff --git a/Emby.Server.Implementations/Localization/Ratings/fr.txt b/Emby.Server.Implementations/Localization/Ratings/fr.csv index f586a3fa9..f586a3fa9 100644 --- a/Emby.Server.Implementations/Localization/Ratings/fr.txt +++ b/Emby.Server.Implementations/Localization/Ratings/fr.csv diff --git a/Emby.Server.Implementations/Localization/Ratings/gb.txt b/Emby.Server.Implementations/Localization/Ratings/gb.csv index c1f7d0452..c1f7d0452 100644 --- a/Emby.Server.Implementations/Localization/Ratings/gb.txt +++ b/Emby.Server.Implementations/Localization/Ratings/gb.csv diff --git a/Emby.Server.Implementations/Localization/Ratings/ie.txt b/Emby.Server.Implementations/Localization/Ratings/ie.csv index e42be5cd4..e42be5cd4 100644 --- a/Emby.Server.Implementations/Localization/Ratings/ie.txt +++ b/Emby.Server.Implementations/Localization/Ratings/ie.csv diff --git a/Emby.Server.Implementations/Localization/Ratings/jp.txt b/Emby.Server.Implementations/Localization/Ratings/jp.csv index a8fc2d143..a8fc2d143 100644 --- a/Emby.Server.Implementations/Localization/Ratings/jp.txt +++ b/Emby.Server.Implementations/Localization/Ratings/jp.csv diff --git a/Emby.Server.Implementations/Localization/Ratings/kz.txt b/Emby.Server.Implementations/Localization/Ratings/kz.csv index 4441c5650..4441c5650 100644 --- a/Emby.Server.Implementations/Localization/Ratings/kz.txt +++ b/Emby.Server.Implementations/Localization/Ratings/kz.csv diff --git a/Emby.Server.Implementations/Localization/Ratings/mx.txt b/Emby.Server.Implementations/Localization/Ratings/mx.csv index 785a8ba22..785a8ba22 100644 --- a/Emby.Server.Implementations/Localization/Ratings/mx.txt +++ b/Emby.Server.Implementations/Localization/Ratings/mx.csv diff --git a/Emby.Server.Implementations/Localization/Ratings/nl.txt b/Emby.Server.Implementations/Localization/Ratings/nl.csv index 8c005092e..8c005092e 100644 --- a/Emby.Server.Implementations/Localization/Ratings/nl.txt +++ b/Emby.Server.Implementations/Localization/Ratings/nl.csv diff --git a/Emby.Server.Implementations/Localization/Ratings/nz.txt b/Emby.Server.Implementations/Localization/Ratings/nz.csv index bba99b764..bba99b764 100644 --- a/Emby.Server.Implementations/Localization/Ratings/nz.txt +++ b/Emby.Server.Implementations/Localization/Ratings/nz.csv diff --git a/Emby.Server.Implementations/Localization/Ratings/ro.txt b/Emby.Server.Implementations/Localization/Ratings/ro.csv index 4089b282f..4089b282f 100644 --- a/Emby.Server.Implementations/Localization/Ratings/ro.txt +++ b/Emby.Server.Implementations/Localization/Ratings/ro.csv diff --git a/Emby.Server.Implementations/Localization/Ratings/uk.txt b/Emby.Server.Implementations/Localization/Ratings/uk.csv index 6c8005b3f..6c8005b3f 100644 --- a/Emby.Server.Implementations/Localization/Ratings/uk.txt +++ b/Emby.Server.Implementations/Localization/Ratings/uk.csv diff --git a/Emby.Server.Implementations/Localization/Ratings/us.txt b/Emby.Server.Implementations/Localization/Ratings/us.csv index 34c897fe3..34c897fe3 100644 --- a/Emby.Server.Implementations/Localization/Ratings/us.txt +++ b/Emby.Server.Implementations/Localization/Ratings/us.csv diff --git a/Emby.Server.Implementations/Localization/TextLocalizer.cs b/Emby.Server.Implementations/Localization/TextLocalizer.cs deleted file mode 100644 index 96591e5e6..000000000 --- a/Emby.Server.Implementations/Localization/TextLocalizer.cs +++ /dev/null @@ -1,63 +0,0 @@ -using System; -using System.Globalization; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; - -namespace Emby.Server.Implementations.Localization -{ - public class TextLocalizer : ITextLocalizer - { - public string RemoveDiacritics(string text) - { - if (text == null) - { - throw new ArgumentNullException(nameof(text)); - } - - var chars = Normalize(text, NormalizationForm.FormD) - .Where(ch => CharUnicodeInfo.GetUnicodeCategory(ch) != UnicodeCategory.NonSpacingMark); - - return Normalize(string.Concat(chars), NormalizationForm.FormC); - } - - private static string Normalize(string text, NormalizationForm form, bool stripStringOnFailure = true) - { - if (stripStringOnFailure) - { - try - { - return text.Normalize(form); - } - catch (ArgumentException) - { - // will throw if input contains invalid unicode chars - // https://mnaoumov.wordpress.com/2014/06/14/stripping-invalid-characters-from-utf-16-strings/ - text = StripInvalidUnicodeCharacters(text); - return Normalize(text, form, false); - } - } - - try - { - return text.Normalize(form); - } - catch (ArgumentException) - { - // if it still fails, return the original text - return text; - } - } - - private static string StripInvalidUnicodeCharacters(string str) - { - var invalidCharactersRegex = new Regex("([\ud800-\udbff](?![\udc00-\udfff]))|((?<![\ud800-\udbff])[\udc00-\udfff])"); - return invalidCharactersRegex.Replace(str, ""); - } - - public string NormalizeFormKD(string text) - { - return text.Normalize(NormalizationForm.FormKD); - } - } -} diff --git a/Emby.Server.Implementations/Localization/iso6392.txt b/Emby.Server.Implementations/Localization/iso6392.txt index f2cea78b6..40f8614f1 100644 --- a/Emby.Server.Implementations/Localization/iso6392.txt +++ b/Emby.Server.Implementations/Localization/iso6392.txt @@ -400,6 +400,7 @@ sog|||Sogdian|sogdien som||so|Somali|somali son|||Songhai languages|songhai, langues sot||st|Sotho, Southern|sotho du Sud +spa||es-mx|Spanish; Latin|espagnol; Latin spa||es|Spanish; Castilian|espagnol; castillan srd||sc|Sardinian|sarde srn|||Sranan Tongo|sranan tongo diff --git a/Emby.Server.Implementations/Networking/IPNetwork/BigIntegerExt.cs b/Emby.Server.Implementations/Networking/IPNetwork/BigIntegerExt.cs index 447cbf403..e4e944839 100644 --- a/Emby.Server.Implementations/Networking/IPNetwork/BigIntegerExt.cs +++ b/Emby.Server.Implementations/Networking/IPNetwork/BigIntegerExt.cs @@ -1,11 +1,10 @@ +using System; using System.Collections.Generic; +using System.Numerics; +using System.Text; -namespace System.Net +namespace Emby.Server.Implementations.Networking.IPNetwork { - using System; - using System.Numerics; - using System.Text; - /// <summary> /// Extension methods to convert <see cref="BigInteger"/> /// instances to hexadecimal, octal, and binary strings. diff --git a/Emby.Server.Implementations/Networking/IPNetwork/IPAddressCollection.cs b/Emby.Server.Implementations/Networking/IPNetwork/IPAddressCollection.cs index c5853135c..a0c5f73af 100644 --- a/Emby.Server.Implementations/Networking/IPNetwork/IPAddressCollection.cs +++ b/Emby.Server.Implementations/Networking/IPNetwork/IPAddressCollection.cs @@ -1,8 +1,10 @@ +using System; using System.Collections; using System.Collections.Generic; +using System.Net; using System.Numerics; -namespace System.Net +namespace Emby.Server.Implementations.Networking.IPNetwork { public class IPAddressCollection : IEnumerable<IPAddress>, IEnumerator<IPAddress> { @@ -29,7 +31,7 @@ namespace System.Net { throw new ArgumentOutOfRangeException(nameof(i)); } - byte width = this._ipnetwork.AddressFamily == Sockets.AddressFamily.InterNetwork ? (byte)32 : (byte)128; + byte width = this._ipnetwork.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork ? (byte)32 : (byte)128; var ipn = this._ipnetwork.Subnet(width); return ipn[i].Network; } diff --git a/Emby.Server.Implementations/Networking/IPNetwork/IPNetwork.cs b/Emby.Server.Implementations/Networking/IPNetwork/IPNetwork.cs index 16f39daf7..d6de61c0c 100644 --- a/Emby.Server.Implementations/Networking/IPNetwork/IPNetwork.cs +++ b/Emby.Server.Implementations/Networking/IPNetwork/IPNetwork.cs @@ -1,10 +1,12 @@ +using System; using System.Collections.Generic; using System.IO; +using System.Net; using System.Net.Sockets; using System.Numerics; using System.Text.RegularExpressions; -namespace System.Net +namespace Emby.Server.Implementations.Networking.IPNetwork { /// <summary> /// IP Network utility class. @@ -60,7 +62,7 @@ namespace System.Net get { - int width = this._family == Sockets.AddressFamily.InterNetwork ? 4 : 16; + int width = this._family == System.Net.Sockets.AddressFamily.InterNetwork ? 4 : 16; var uintBroadcast = this._network + this._netmask.PositiveReverse(width); return uintBroadcast; } @@ -73,7 +75,7 @@ namespace System.Net { get { - if (this._family == Sockets.AddressFamily.InterNetworkV6) + if (this._family == System.Net.Sockets.AddressFamily.InterNetworkV6) { return null; } @@ -88,7 +90,7 @@ namespace System.Net { get { - var fisrt = this._family == Sockets.AddressFamily.InterNetworkV6 + var fisrt = this._family == System.Net.Sockets.AddressFamily.InterNetworkV6 ? this._network : (this.Usable <= 0) ? this._network : this._network + 1; return IPNetwork.ToIPAddress(fisrt, this._family); @@ -102,7 +104,7 @@ namespace System.Net { get { - var last = this._family == Sockets.AddressFamily.InterNetworkV6 + var last = this._family == System.Net.Sockets.AddressFamily.InterNetworkV6 ? this._broadcast : (this.Usable <= 0) ? this._network : this._broadcast - 1; return IPNetwork.ToIPAddress(last, this._family); @@ -117,7 +119,7 @@ namespace System.Net get { - if (this._family == Sockets.AddressFamily.InterNetworkV6) + if (this._family == System.Net.Sockets.AddressFamily.InterNetworkV6) { return this.Total; } @@ -136,7 +138,7 @@ namespace System.Net get { - int max = this._family == Sockets.AddressFamily.InterNetwork ? 32 : 128; + int max = this._family == System.Net.Sockets.AddressFamily.InterNetwork ? 32 : 128; var count = BigInteger.Pow(2, (max - _cidr)); return count; } @@ -161,7 +163,7 @@ namespace System.Net IPNetwork(BigInteger ipaddress, AddressFamily family, byte cidr) { - int maxCidr = family == Sockets.AddressFamily.InterNetwork ? 32 : 128; + int maxCidr = family == System.Net.Sockets.AddressFamily.InterNetwork ? 32 : 128; if (cidr > maxCidr) { throw new ArgumentOutOfRangeException(nameof(cidr)); @@ -930,7 +932,7 @@ namespace System.Net /// return; /// } - int maxCidr = family == Sockets.AddressFamily.InterNetwork ? 32 : 128; + int maxCidr = family == System.Net.Sockets.AddressFamily.InterNetwork ? 32 : 128; if (cidr > maxCidr) { if (tryParse == false) @@ -1303,7 +1305,7 @@ namespace System.Net return; } - int maxCidr = network._family == Sockets.AddressFamily.InterNetwork ? 32 : 128; + int maxCidr = network._family == System.Net.Sockets.AddressFamily.InterNetwork ? 32 : 128; if (cidr > maxCidr) { if (trySubnet == false) diff --git a/Emby.Server.Implementations/Networking/IPNetwork/IPNetworkCollection.cs b/Emby.Server.Implementations/Networking/IPNetwork/IPNetworkCollection.cs index 7d3106624..4cda421e5 100644 --- a/Emby.Server.Implementations/Networking/IPNetwork/IPNetworkCollection.cs +++ b/Emby.Server.Implementations/Networking/IPNetwork/IPNetworkCollection.cs @@ -1,8 +1,9 @@ +using System; using System.Collections; using System.Collections.Generic; using System.Numerics; -namespace System.Net +namespace Emby.Server.Implementations.Networking.IPNetwork { public class IPNetworkCollection : IEnumerable<IPNetwork>, IEnumerator<IPNetwork> { @@ -25,7 +26,7 @@ namespace System.Net IPNetworkCollection(IPNetwork ipnetwork, byte cidrSubnet) { - int maxCidr = ipnetwork.AddressFamily == Sockets.AddressFamily.InterNetwork ? 32 : 128; + int maxCidr = ipnetwork.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork ? 32 : 128; if (cidrSubnet > maxCidr) { throw new ArgumentOutOfRangeException(nameof(cidrSubnet)); @@ -61,7 +62,7 @@ namespace System.Net throw new ArgumentOutOfRangeException(nameof(i)); } - var last = this._ipnetwork.AddressFamily == Sockets.AddressFamily.InterNetworkV6 + var last = this._ipnetwork.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6 ? this._lastUsable : this._broadcast; var increment = (last - this._network) / this.Count; var uintNetwork = this._network + ((increment + 1) * i); diff --git a/Emby.Server.Implementations/Networking/NetworkManager.cs b/Emby.Server.Implementations/Networking/NetworkManager.cs index f4b9f84dc..60cc9b88e 100644 --- a/Emby.Server.Implementations/Networking/NetworkManager.cs +++ b/Emby.Server.Implementations/Networking/NetworkManager.cs @@ -111,7 +111,8 @@ namespace Emby.Server.Implementations.Networking .OrderBy(i => i.AddressFamily == AddressFamily.InterNetwork ? 0 : 1) .ThenBy(i => listClone.IndexOf(i)) .Where(FilterIpAddress) - .DistinctBy(i => i.ToString()) + .GroupBy(i => i.ToString()) + .Select(x => x.First()) .ToList(); } @@ -280,7 +281,7 @@ namespace Emby.Server.Implementations.Networking if (normalizedSubnet.IndexOf('/') != -1) { - var ipnetwork = IPNetwork.Parse(normalizedSubnet); + var ipnetwork = IPNetwork.IPNetwork.Parse(normalizedSubnet); if (ipnetwork.Contains(address)) { return true; @@ -429,7 +430,8 @@ namespace Emby.Server.Implementations.Networking return new List<IPAddress>(); } - }).DistinctBy(i => i.ToString()) + }).GroupBy(i => i.ToString()) + .Select(x => x.First()) .ToList(); } diff --git a/Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs b/Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs index 223153164..8a7c1492d 100644 --- a/Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs +++ b/Emby.Server.Implementations/Playlists/PlaylistImageProvider.cs @@ -13,7 +13,6 @@ using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Playlists; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.IO; using MediaBrowser.Model.Querying; @@ -64,7 +63,8 @@ namespace Emby.Server.Implementations.Playlists }) .Where(i => i != null) .OrderBy(i => Guid.NewGuid()) - .DistinctBy(i => i.Id) + .GroupBy(x => x.Id) + .Select(x => x.First()) .ToList(); } } diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs index 2b648b04b..08bb39578 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs +++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs @@ -10,7 +10,6 @@ using MediaBrowser.Common.Progress; using MediaBrowser.Model.Events; using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.System; using MediaBrowser.Model.Tasks; using Microsoft.Extensions.Logging; diff --git a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs index b8479fd26..595c3037d 100644 --- a/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs +++ b/Emby.Server.Implementations/ScheduledTasks/TaskManager.cs @@ -1,14 +1,12 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Threading.Tasks; using MediaBrowser.Common.Configuration; using MediaBrowser.Model.Events; using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.System; using MediaBrowser.Model.Tasks; using Microsoft.Extensions.Logging; @@ -74,38 +72,6 @@ namespace Emby.Server.Implementations.ScheduledTasks ScheduledTasks = new IScheduledTaskWorker[] { }; } - private void RunStartupTasks() - { - var path = Path.Combine(ApplicationPaths.CachePath, "startuptasks.txt"); - - // ToDo: Fix this shit - if (!File.Exists(path)) - return; - - List<string> lines; - - try - { - lines = File.ReadAllLines(path).Where(i => !string.IsNullOrWhiteSpace(i)).Distinct(StringComparer.OrdinalIgnoreCase).ToList(); - - foreach (var key in lines) - { - var task = ScheduledTasks.FirstOrDefault(i => string.Equals(i.ScheduledTask.Key, key, StringComparison.OrdinalIgnoreCase)); - - if (task != null) - { - QueueScheduledTask(task, new TaskOptions()); - } - } - - _fileSystem.DeleteFile(path); - } - catch - { - return; - } - } - /// <summary> /// Cancels if running and queue. /// </summary> @@ -247,14 +213,9 @@ namespace Emby.Server.Implementations.ScheduledTasks /// <param name="tasks">The tasks.</param> public void AddTasks(IEnumerable<IScheduledTask> tasks) { - var myTasks = ScheduledTasks.ToList(); - - var list = tasks.ToList(); - myTasks.AddRange(list.Select(t => new ScheduledTaskWorker(t, ApplicationPaths, this, JsonSerializer, Logger, _fileSystem))); - - ScheduledTasks = myTasks.ToArray(); + var list = tasks.Select(t => new ScheduledTaskWorker(t, ApplicationPaths, this, JsonSerializer, Logger, _fileSystem)); - RunStartupTasks(); + ScheduledTasks = ScheduledTasks.Concat(list).ToArray(); } /// <summary> diff --git a/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs index 5373b4392..81fdb96d2 100644 --- a/Emby.Server.Implementations/ScheduledTasks/ChapterImagesTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/ChapterImagesTask.cs @@ -68,8 +68,6 @@ namespace Emby.Server.Implementations.ScheduledTasks }; } - public string Key => "RefreshChapterImages"; - /// <summary> /// Returns the task to be executed /// </summary> @@ -161,22 +159,18 @@ namespace Emby.Server.Implementations.ScheduledTasks } } - /// <summary> - /// Gets the name of the task - /// </summary> - /// <value>The name.</value> public string Name => "Chapter image extraction"; - /// <summary> - /// Gets the description. - /// </summary> - /// <value>The description.</value> public string Description => "Creates thumbnails for videos that have chapters."; - /// <summary> - /// Gets the category. - /// </summary> - /// <value>The category.</value> public string Category => "Library"; + + public string Key => "RefreshChapterImages"; + + public bool IsHidden => false; + + public bool IsEnabled => true; + + public bool IsLogged => true; } } diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs index 52077b242..6ec83b5c0 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteCacheFileTask.cs @@ -158,31 +158,15 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks } } - /// <summary> - /// Gets the name of the task - /// </summary> - /// <value>The name.</value> public string Name => "Cache file cleanup"; - public string Key => "DeleteCacheFiles"; - - /// <summary> - /// Gets the description. - /// </summary> - /// <value>The description.</value> public string Description => "Deletes cache files no longer needed by the system"; - /// <summary> - /// Gets the category. - /// </summary> - /// <value>The category.</value> public string Category => "Maintenance"; - /// <summary> - /// Gets a value indicating whether this instance is hidden. - /// </summary> - /// <value><c>true</c> if this instance is hidden; otherwise, <c>false</c>.</value> - public bool IsHidden => true; + public string Key => "DeleteCacheFiles"; + + public bool IsHidden => false; public bool IsEnabled => true; diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs index a57fe4945..e468c301a 100644 --- a/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs @@ -81,31 +81,15 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks return Task.CompletedTask; } - public string Key => "CleanLogFiles"; - - /// <summary> - /// Gets the name of the task - /// </summary> - /// <value>The name.</value> public string Name => "Log file cleanup"; - /// <summary> - /// Gets the description. - /// </summary> - /// <value>The description.</value> public string Description => string.Format("Deletes log files that are more than {0} days old.", ConfigurationManager.CommonConfiguration.LogFileRetentionDays); - /// <summary> - /// Gets the category. - /// </summary> - /// <value>The category.</value> public string Category => "Maintenance"; - /// <summary> - /// Gets a value indicating whether this instance is hidden. - /// </summary> - /// <value><c>true</c> if this instance is hidden; otherwise, <c>false</c>.</value> - public bool IsHidden => true; + public string Key => "CleanLogFiles"; + + public bool IsHidden => false; public bool IsEnabled => true; diff --git a/Emby.Server.Implementations/ScheduledTasks/PeopleValidationTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs index 68031170f..d70799c47 100644 --- a/Emby.Server.Implementations/ScheduledTasks/PeopleValidationTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/PeopleValidationTask.cs @@ -47,8 +47,6 @@ namespace Emby.Server.Implementations.ScheduledTasks }; } - public string Key => "RefreshPeople"; - /// <summary> /// Returns the task to be executed /// </summary> @@ -60,22 +58,18 @@ namespace Emby.Server.Implementations.ScheduledTasks return _libraryManager.ValidatePeople(cancellationToken, progress); } - /// <summary> - /// Gets the name of the task - /// </summary> - /// <value>The name.</value> public string Name => "Refresh people"; - /// <summary> - /// Gets the description. - /// </summary> - /// <value>The description.</value> public string Description => "Updates metadata for actors and directors in your media library."; - /// <summary> - /// Gets the category. - /// </summary> - /// <value>The category.</value> public string Category => "Library"; + + public string Key => "RefreshPeople"; + + public bool IsHidden => false; + + public bool IsEnabled => true; + + public bool IsLogged => true; } } diff --git a/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs new file mode 100644 index 000000000..c6431c311 --- /dev/null +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/PluginUpdateTask.cs @@ -0,0 +1,119 @@ +using MediaBrowser.Common; +using MediaBrowser.Common.Updates; +using MediaBrowser.Model.Net; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using MediaBrowser.Common.Progress; +using MediaBrowser.Model.Tasks; +using Microsoft.Extensions.Logging; + +namespace Emby.Server.Implementations.ScheduledTasks +{ + /// <summary> + /// Plugin Update Task + /// </summary> + public class PluginUpdateTask : IScheduledTask, IConfigurableScheduledTask + { + /// <summary> + /// The _logger + /// </summary> + private readonly ILogger _logger; + + private readonly IInstallationManager _installationManager; + + private readonly IApplicationHost _appHost; + + public PluginUpdateTask(ILogger logger, IInstallationManager installationManager, IApplicationHost appHost) + { + _logger = logger; + _installationManager = installationManager; + _appHost = appHost; + } + + /// <summary> + /// Creates the triggers that define when the task will run + /// </summary> + /// <returns>IEnumerable{BaseTaskTrigger}.</returns> + public IEnumerable<TaskTriggerInfo> GetDefaultTriggers() + { + return new[] { + + // At startup + new TaskTriggerInfo {Type = TaskTriggerInfo.TriggerStartup}, + + // Every so often + new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks} + }; + } + + /// <summary> + /// Update installed plugins + /// </summary> + /// <param name="cancellationToken">The cancellation token.</param> + /// <param name="progress">The progress.</param> + /// <returns>Task.</returns> + public async Task Execute(CancellationToken cancellationToken, IProgress<double> progress) + { + progress.Report(0); + + var packagesToInstall = (await _installationManager.GetAvailablePluginUpdates(typeof(PluginUpdateTask).Assembly.GetName().Version, true, cancellationToken).ConfigureAwait(false)).ToList(); + + progress.Report(10); + + var numComplete = 0; + + foreach (var package in packagesToInstall) + { + cancellationToken.ThrowIfCancellationRequested(); + + try + { + await _installationManager.InstallPackage(package, true, new SimpleProgress<double>(), cancellationToken).ConfigureAwait(false); + } + catch (OperationCanceledException) + { + // InstallPackage has it's own inner cancellation token, so only throw this if it's ours + if (cancellationToken.IsCancellationRequested) + { + throw; + } + } + catch (HttpException ex) + { + _logger.LogError(ex, "Error downloading {0}", package.name); + } + catch (IOException ex) + { + _logger.LogError(ex, "Error updating {0}", package.name); + } + + // Update progress + lock (progress) + { + numComplete++; + progress.Report(90.0 * numComplete / packagesToInstall.Count + 10); + } + } + + progress.Report(100); + } + + public string Name => "Check for plugin updates"; + + public string Description => "Downloads and installs updates for plugins that are configured to update automatically."; + + public string Category => "Application"; + + public string Key => "PluginUpdates"; + + public bool IsHidden => false; + + public bool IsEnabled => true; + + public bool IsLogged => true; + } +} diff --git a/Emby.Server.Implementations/ScheduledTasks/RefreshMediaLibraryTask.cs b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs index f6fa64d13..1a3d85ad7 100644 --- a/Emby.Server.Implementations/ScheduledTasks/RefreshMediaLibraryTask.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Tasks/RefreshMediaLibraryTask.cs @@ -58,24 +58,18 @@ namespace Emby.Server.Implementations.ScheduledTasks return ((LibraryManager)_libraryManager).ValidateMediaLibraryInternal(progress, cancellationToken); } - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> public string Name => "Scan media library"; - /// <summary> - /// Gets the description. - /// </summary> - /// <value>The description.</value> public string Description => "Scans your media library and refreshes metatata based on configuration."; - /// <summary> - /// Gets the category. - /// </summary> - /// <value>The category.</value> public string Category => "Library"; public string Key => "RefreshLibrary"; + + public bool IsHidden => false; + + public bool IsEnabled => true; + + public bool IsLogged => true; } } diff --git a/Emby.Server.Implementations/ScheduledTasks/DailyTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs index 98685cebe..98685cebe 100644 --- a/Emby.Server.Implementations/ScheduledTasks/DailyTrigger.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs diff --git a/Emby.Server.Implementations/ScheduledTasks/IntervalTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs index 3a34da3af..3a34da3af 100644 --- a/Emby.Server.Implementations/ScheduledTasks/IntervalTrigger.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/IntervalTrigger.cs diff --git a/Emby.Server.Implementations/ScheduledTasks/StartupTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/StartupTrigger.cs index 08ff4f55f..08ff4f55f 100644 --- a/Emby.Server.Implementations/ScheduledTasks/StartupTrigger.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/StartupTrigger.cs diff --git a/Emby.Server.Implementations/ScheduledTasks/WeeklyTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs index 2a6a7b13c..2a6a7b13c 100644 --- a/Emby.Server.Implementations/ScheduledTasks/WeeklyTrigger.cs +++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/WeeklyTrigger.cs diff --git a/Emby.Server.Implementations/Serialization/JsonSerializer.cs b/Emby.Server.Implementations/Serialization/JsonSerializer.cs index 53ef5d60c..44898d498 100644 --- a/Emby.Server.Implementations/Serialization/JsonSerializer.cs +++ b/Emby.Server.Implementations/Serialization/JsonSerializer.cs @@ -3,9 +3,8 @@ using System.IO; using System.Threading.Tasks; using MediaBrowser.Model.IO; using MediaBrowser.Model.Serialization; -using Microsoft.Extensions.Logging; -namespace Emby.Common.Implementations.Serialization +namespace Emby.Server.Implementations.Serialization { /// <summary> /// Provides a wrapper around third party json serialization. diff --git a/Emby.Server.Implementations/ServerApplicationPaths.cs b/Emby.Server.Implementations/ServerApplicationPaths.cs index edea10a07..36975df50 100644 --- a/Emby.Server.Implementations/ServerApplicationPaths.cs +++ b/Emby.Server.Implementations/ServerApplicationPaths.cs @@ -18,8 +18,13 @@ namespace Emby.Server.Implementations string appFolderPath, string applicationResourcesPath, string logDirectoryPath = null, - string configurationDirectoryPath = null) - : base(programDataPath, appFolderPath, logDirectoryPath, configurationDirectoryPath) + string configurationDirectoryPath = null, + string cacheDirectoryPath = null) + : base(programDataPath, + appFolderPath, + logDirectoryPath, + configurationDirectoryPath, + cacheDirectoryPath) { ApplicationResourcesPath = applicationResourcesPath; } @@ -136,12 +141,6 @@ namespace Emby.Server.Implementations return path; } - /// <summary> - /// Gets the game genre path. - /// </summary> - /// <value>The game genre path.</value> - public string GameGenrePath => Path.Combine(InternalMetadataPath, "GameGenre"); - private string _internalMetadataPath; public string InternalMetadataPath { diff --git a/Emby.Server.Implementations/Services/RequestHelper.cs b/Emby.Server.Implementations/Services/RequestHelper.cs index 24e9cbfa4..2563cac99 100644 --- a/Emby.Server.Implementations/Services/RequestHelper.cs +++ b/Emby.Server.Implementations/Services/RequestHelper.cs @@ -45,7 +45,7 @@ namespace Emby.Server.Implementations.Services { return contentType == null ? null - : contentType.Split(';')[0].ToLower().Trim(); + : contentType.Split(';')[0].ToLowerInvariant().Trim(); } } diff --git a/Emby.Server.Implementations/Services/ResponseHelper.cs b/Emby.Server.Implementations/Services/ResponseHelper.cs index 16de1a083..dc9975347 100644 --- a/Emby.Server.Implementations/Services/ResponseHelper.cs +++ b/Emby.Server.Implementations/Services/ResponseHelper.cs @@ -70,7 +70,7 @@ namespace Emby.Server.Implementations.Services response.ContentType = defaultContentType; } - if (new HashSet<string> { "application/json", }.Contains(response.ContentType)) + if (response.ContentType == "application/json") { response.ContentType += "; charset=utf-8"; } diff --git a/Emby.Server.Implementations/Services/ServiceExec.cs b/Emby.Server.Implementations/Services/ServiceExec.cs index 45c918fa1..79f5c59e6 100644 --- a/Emby.Server.Implementations/Services/ServiceExec.cs +++ b/Emby.Server.Implementations/Services/ServiceExec.cs @@ -23,8 +23,6 @@ namespace Emby.Server.Implementations.Services "POLL", "SUBSCRIBE", "UNSUBSCRIBE" }; - public static HashSet<string> AllVerbsSet = new HashSet<string>(AllVerbs); - public static List<MethodInfo> GetActions(this Type serviceType) { var list = new List<MethodInfo>(); @@ -98,7 +96,7 @@ namespace Emby.Server.Implementations.Services return Task.FromResult(response); } - var expectedMethodName = actionName.Substring(0, 1) + actionName.Substring(1).ToLower(); + var expectedMethodName = actionName.Substring(0, 1) + actionName.Substring(1).ToLowerInvariant(); throw new NotImplementedException(string.Format("Could not find method named {1}({0}) or Any({0}) on Service {2}", requestDto.GetType().GetMethodName(), expectedMethodName, serviceType.GetMethodName())); } diff --git a/Emby.Server.Implementations/Services/ServiceMethod.cs b/Emby.Server.Implementations/Services/ServiceMethod.cs index 7add72815..5018bf4a2 100644 --- a/Emby.Server.Implementations/Services/ServiceMethod.cs +++ b/Emby.Server.Implementations/Services/ServiceMethod.cs @@ -11,7 +11,7 @@ namespace Emby.Server.Implementations.Services public static string Key(Type serviceType, string method, string requestDtoName) { - return serviceType.FullName + " " + method.ToUpper() + " " + requestDtoName; + return serviceType.FullName + " " + method.ToUpperInvariant() + " " + requestDtoName; } } } diff --git a/Emby.Server.Implementations/Services/ServicePath.cs b/Emby.Server.Implementations/Services/ServicePath.cs index 7e1993b71..f575baca3 100644 --- a/Emby.Server.Implementations/Services/ServicePath.cs +++ b/Emby.Server.Implementations/Services/ServicePath.cs @@ -60,7 +60,7 @@ namespace Emby.Server.Implementations.Services public static string[] GetPathPartsForMatching(string pathInfo) { - return pathInfo.ToLower().Split(new[] { PathSeperatorChar }, StringSplitOptions.RemoveEmptyEntries); + return pathInfo.ToLowerInvariant().Split(new[] { PathSeperatorChar }, StringSplitOptions.RemoveEmptyEntries); } public static List<string> GetFirstMatchHashKeys(string[] pathPartsForMatching) @@ -104,7 +104,7 @@ namespace Emby.Server.Implementations.Services this.Description = description; this.restPath = path; - this.Verbs = string.IsNullOrWhiteSpace(verbs) ? ServiceExecExtensions.AllVerbs : verbs.ToUpper().Split(new[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries); + this.Verbs = string.IsNullOrWhiteSpace(verbs) ? ServiceExecExtensions.AllVerbs : verbs.ToUpperInvariant().Split(new[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries); var componentsList = new List<string>(); @@ -154,7 +154,7 @@ namespace Emby.Server.Implementations.Services } else { - this.literalsToMatch[i] = component.ToLower(); + this.literalsToMatch[i] = component.ToLowerInvariant(); if (firstLiteralMatch == null) { @@ -189,7 +189,7 @@ namespace Emby.Server.Implementations.Services foreach (var propertyInfo in GetSerializableProperties(RequestType)) { var propertyName = propertyInfo.Name; - propertyNamesMap.Add(propertyName.ToLower(), propertyName); + propertyNamesMap.Add(propertyName.ToLowerInvariant(), propertyName); } } @@ -483,7 +483,7 @@ namespace Emby.Server.Implementations.Services continue; } - if (!this.propertyNamesMap.TryGetValue(variableName.ToLower(), out var propertyNameOnRequest)) + if (!this.propertyNamesMap.TryGetValue(variableName.ToLowerInvariant(), out var propertyNameOnRequest)) { if (string.Equals("ignore", variableName, StringComparison.OrdinalIgnoreCase)) { diff --git a/Emby.Server.Implementations/Services/SwaggerService.cs b/Emby.Server.Implementations/Services/SwaggerService.cs index 9bceeabec..3e6970eef 100644 --- a/Emby.Server.Implementations/Services/SwaggerService.cs +++ b/Emby.Server.Implementations/Services/SwaggerService.cs @@ -216,40 +216,28 @@ namespace Emby.Server.Implementations.Services { var responses = new Dictionary<string, SwaggerResponse> { + { "200", new SwaggerResponse { description = "OK" } } }; - responses["200"] = new SwaggerResponse + var apiKeySecurity = new Dictionary<string, string[]> { - description = "OK" + { "api_key", Array.Empty<string>() } }; - var security = new List<Dictionary<string, string[]>>(); - - var apiKeySecurity = new Dictionary<string, string[]>(); - apiKeySecurity["api_key"] = Array.Empty<string>(); - - security.Add(apiKeySecurity); - - result[verb.ToLower()] = new SwaggerMethod + result[verb.ToLowerInvariant()] = new SwaggerMethod { summary = info.Summary, description = info.Description, - produces = new[] - { - "application/json" - }, - consumes = new[] - { - "application/json" - }, + produces = new[] { "application/json" }, + consumes = new[] { "application/json" }, operationId = info.RequestType.Name, tags = Array.Empty<string>(), - parameters = new SwaggerParam[] { }, + parameters = Array.Empty<SwaggerParam>(), responses = responses, - security = security.ToArray() + security = new [] { apiKeySecurity } }; } diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs index b03345e03..fa0ab62d3 100644 --- a/Emby.Server.Implementations/Session/SessionManager.cs +++ b/Emby.Server.Implementations/Session/SessionManager.cs @@ -27,7 +27,6 @@ using MediaBrowser.Model.Library; using MediaBrowser.Model.Querying; using MediaBrowser.Model.Serialization; using MediaBrowser.Model.Session; -using MediaBrowser.Model.Threading; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.Session @@ -60,7 +59,6 @@ namespace Emby.Server.Implementations.Session private readonly IAuthenticationRepository _authRepo; private readonly IDeviceManager _deviceManager; - private readonly ITimerFactory _timerFactory; /// <summary> /// The _active connections @@ -103,8 +101,7 @@ namespace Emby.Server.Implementations.Session IHttpClient httpClient, IAuthenticationRepository authRepo, IDeviceManager deviceManager, - IMediaSourceManager mediaSourceManager, - ITimerFactory timerFactory) + IMediaSourceManager mediaSourceManager) { _userDataManager = userDataManager; _logger = loggerFactory.CreateLogger(nameof(SessionManager)); @@ -119,7 +116,6 @@ namespace Emby.Server.Implementations.Session _authRepo = authRepo; _deviceManager = deviceManager; _mediaSourceManager = mediaSourceManager; - _timerFactory = timerFactory; _deviceManager.DeviceOptionsUpdated += _deviceManager_DeviceOptionsUpdated; } @@ -503,13 +499,13 @@ namespace Emby.Server.Implementations.Session return users; } - private ITimer _idleTimer; + private Timer _idleTimer; private void StartIdleCheckTimer() { if (_idleTimer == null) { - _idleTimer = _timerFactory.Create(CheckForIdlePlayback, null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)); + _idleTimer = new Timer(CheckForIdlePlayback, null, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5)); } } private void StopIdleCheckTimer() @@ -606,7 +602,7 @@ namespace Emby.Server.Implementations.Session ClearTranscodingInfo(session.DeviceId); } - session.StartAutomaticProgress(_timerFactory, info); + session.StartAutomaticProgress(info); var users = GetUsers(session); @@ -717,7 +713,7 @@ namespace Emby.Server.Implementations.Session if (!isAutomated) { - session.StartAutomaticProgress(_timerFactory, info); + session.StartAutomaticProgress(info); } StartIdleCheckTimer(); diff --git a/Emby.Server.Implementations/Sorting/GameSystemComparer.cs b/Emby.Server.Implementations/Sorting/GameSystemComparer.cs deleted file mode 100644 index 2a04bae3c..000000000 --- a/Emby.Server.Implementations/Sorting/GameSystemComparer.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; - -namespace Emby.Server.Implementations.Sorting -{ - public class GameSystemComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return string.Compare(GetValue(x), GetValue(y), StringComparison.CurrentCultureIgnoreCase); - } - - /// <summary> - /// Gets the value. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>System.String.</returns> - private static string GetValue(BaseItem x) - { - var game = x as Game; - - if (game != null) - { - return game.GameSystem; - } - - var system = x as GameSystem; - - if (system != null) - { - return system.GameSystemName; - } - - return string.Empty; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name => ItemSortBy.GameSystem; - } -} diff --git a/Emby.Server.Implementations/Sorting/PlayersComparer.cs b/Emby.Server.Implementations/Sorting/PlayersComparer.cs deleted file mode 100644 index e3652f36b..000000000 --- a/Emby.Server.Implementations/Sorting/PlayersComparer.cs +++ /dev/null @@ -1,43 +0,0 @@ -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Sorting; -using MediaBrowser.Model.Querying; - -namespace Emby.Server.Implementations.Sorting -{ - public class PlayersComparer : IBaseItemComparer - { - /// <summary> - /// Compares the specified x. - /// </summary> - /// <param name="x">The x.</param> - /// <param name="y">The y.</param> - /// <returns>System.Int32.</returns> - public int Compare(BaseItem x, BaseItem y) - { - return GetValue(x).CompareTo(GetValue(y)); - } - - /// <summary> - /// Gets the value. - /// </summary> - /// <param name="x">The x.</param> - /// <returns>System.String.</returns> - private static int GetValue(BaseItem x) - { - var game = x as Game; - - if (game != null) - { - return game.PlayersSupported ?? 0; - } - - return 0; - } - - /// <summary> - /// Gets the name. - /// </summary> - /// <value>The name.</value> - public string Name => ItemSortBy.Players; - } -} diff --git a/Emby.Server.Implementations/StartupOptions.cs b/Emby.Server.Implementations/StartupOptions.cs deleted file mode 100644 index 221263634..000000000 --- a/Emby.Server.Implementations/StartupOptions.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Linq; - -namespace Emby.Server.Implementations -{ - public class StartupOptions - { - private readonly string[] _options; - - public StartupOptions(string[] commandLineArgs) - { - _options = commandLineArgs; - } - - public bool ContainsOption(string option) - => _options.Contains(option, StringComparer.OrdinalIgnoreCase); - - public string GetOption(string name) - { - int index = Array.IndexOf(_options, name); - - if (index == -1) - { - return null; - } - - return _options.ElementAtOrDefault(index + 1); - } - } -} diff --git a/Emby.Server.Implementations/Threading/CommonTimer.cs b/Emby.Server.Implementations/Threading/CommonTimer.cs deleted file mode 100644 index 5a05da564..000000000 --- a/Emby.Server.Implementations/Threading/CommonTimer.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Threading; -using MediaBrowser.Model.Threading; - -namespace Emby.Server.Implementations.Threading -{ - public class CommonTimer : ITimer - { - private readonly Timer _timer; - - public CommonTimer(Action<object> callback, object state, TimeSpan dueTime, TimeSpan period) - { - _timer = new Timer(new TimerCallback(callback), state, dueTime, period); - } - - public CommonTimer(Action<object> callback, object state, int dueTimeMs, int periodMs) - { - _timer = new Timer(new TimerCallback(callback), state, dueTimeMs, periodMs); - } - - public void Change(TimeSpan dueTime, TimeSpan period) - { - _timer.Change(dueTime, period); - } - - public void Change(int dueTimeMs, int periodMs) - { - _timer.Change(dueTimeMs, periodMs); - } - - public void Dispose() - { - _timer.Dispose(); - } - } -} diff --git a/Emby.Server.Implementations/Threading/TimerFactory.cs b/Emby.Server.Implementations/Threading/TimerFactory.cs deleted file mode 100644 index ca50064c7..000000000 --- a/Emby.Server.Implementations/Threading/TimerFactory.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; -using MediaBrowser.Model.Threading; - -namespace Emby.Server.Implementations.Threading -{ - public class TimerFactory : ITimerFactory - { - public ITimer Create(Action<object> callback, object state, TimeSpan dueTime, TimeSpan period) - { - return new CommonTimer(callback, state, dueTime, period); - } - - public ITimer Create(Action<object> callback, object state, int dueTimeMs, int periodMs) - { - return new CommonTimer(callback, state, dueTimeMs, periodMs); - } - } -} diff --git a/Emby.Server.Implementations/Updates/InstallationManager.cs b/Emby.Server.Implementations/Updates/InstallationManager.cs index 552155635..dc7f57f27 100644 --- a/Emby.Server.Implementations/Updates/InstallationManager.cs +++ b/Emby.Server.Implementations/Updates/InstallationManager.cs @@ -169,10 +169,8 @@ namespace Emby.Server.Implementations.Updates string packageType = null, Version applicationVersion = null) { - // TODO cvium: when plugins get back this would need to be fixed - // var packages = await GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false); - - return new List<PackageInfo>(); //FilterPackages(packages, packageType, applicationVersion); + var packages = await GetAvailablePackagesWithoutRegistrationInfo(cancellationToken).ConfigureAwait(false); + return FilterPackages(packages, packageType, applicationVersion); } /// <summary> @@ -184,12 +182,10 @@ namespace Emby.Server.Implementations.Updates { using (var response = await _httpClient.SendAsync(new HttpRequestOptions { - Url = "https://www.mb3admin.local/admin/service/EmbyPackages.json", + Url = "https://repo.jellyfin.org/releases/plugin/manifest.json", CancellationToken = cancellationToken, Progress = new SimpleProgress<double>(), - CacheLength = GetCacheLength(), - CacheMode = CacheMode.Unconditional - + CacheLength = GetCacheLength() }, "GET").ConfigureAwait(false)) { using (var stream = response.Content) diff --git a/Emby.Server.Implementations/UserViews/CollectionFolderImageProvider.cs b/Emby.Server.Implementations/UserViews/CollectionFolderImageProvider.cs index 8788cfc26..ce6c2cd87 100644 --- a/Emby.Server.Implementations/UserViews/CollectionFolderImageProvider.cs +++ b/Emby.Server.Implementations/UserViews/CollectionFolderImageProvider.cs @@ -43,10 +43,6 @@ namespace Emby.Server.Implementations.UserViews { includeItemTypes = new string[] { "Book", "AudioBook" }; } - else if (string.Equals(viewType, CollectionType.Games)) - { - includeItemTypes = new string[] { "Game" }; - } else if (string.Equals(viewType, CollectionType.BoxSets)) { includeItemTypes = new string[] { "BoxSet" }; diff --git a/Emby.Server.Implementations/UserViews/DynamicImageProvider.cs b/Emby.Server.Implementations/UserViews/DynamicImageProvider.cs index 937db3f23..4ec68e550 100644 --- a/Emby.Server.Implementations/UserViews/DynamicImageProvider.cs +++ b/Emby.Server.Implementations/UserViews/DynamicImageProvider.cs @@ -12,7 +12,6 @@ using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Extensions; using MediaBrowser.Model.IO; namespace Emby.Server.Implementations.UserViews @@ -83,7 +82,8 @@ namespace Emby.Server.Implementations.UserViews return i; - }).DistinctBy(i => i.Id); + }).GroupBy(x => x.Id) + .Select(x => x.First()); if (isUsingCollectionStrip) { diff --git a/Emby.Server.Implementations/UserViews/FolderImageProvider.cs b/Emby.Server.Implementations/UserViews/FolderImageProvider.cs index 7629f6039..c810004ab 100644 --- a/Emby.Server.Implementations/UserViews/FolderImageProvider.cs +++ b/Emby.Server.Implementations/UserViews/FolderImageProvider.cs @@ -11,7 +11,7 @@ using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.Querying; -namespace Emby.Server.Implementations.Photos +namespace Emby.Server.Implementations.UserViews { public abstract class BaseFolderImageProvider<T> : BaseDynamicImageProvider<T> where T : Folder, new() |
