mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-04-15 06:42:18 +01:00
Merge branch 'master' into gzip
This commit is contained in:
@@ -82,6 +82,7 @@ using MediaBrowser.Controller.SyncPlay;
|
||||
using MediaBrowser.Controller.TV;
|
||||
using MediaBrowser.LocalMetadata.Savers;
|
||||
using MediaBrowser.MediaEncoding.BdInfo;
|
||||
using MediaBrowser.MediaEncoding.Subtitles;
|
||||
using MediaBrowser.Model.Cryptography;
|
||||
using MediaBrowser.Model.Dlna;
|
||||
using MediaBrowser.Model.Globalization;
|
||||
@@ -110,7 +111,7 @@ namespace Emby.Server.Implementations
|
||||
/// <summary>
|
||||
/// Class CompositionRoot.
|
||||
/// </summary>
|
||||
public abstract class ApplicationHost : IServerApplicationHost, IDisposable
|
||||
public abstract class ApplicationHost : IServerApplicationHost, IAsyncDisposable, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// The environment variable prefixes to log at server startup.
|
||||
@@ -631,7 +632,8 @@ namespace Emby.Server.Implementations
|
||||
serviceCollection.AddSingleton<IAuthService, AuthService>();
|
||||
serviceCollection.AddSingleton<IQuickConnect, QuickConnectManager>();
|
||||
|
||||
serviceCollection.AddSingleton<ISubtitleEncoder, MediaBrowser.MediaEncoding.Subtitles.SubtitleEncoder>();
|
||||
serviceCollection.AddSingleton<ISubtitleParser, SubtitleEditParser>();
|
||||
serviceCollection.AddSingleton<ISubtitleEncoder, SubtitleEncoder>();
|
||||
|
||||
serviceCollection.AddSingleton<IAttachmentExtractor, MediaBrowser.MediaEncoding.Attachments.AttachmentExtractor>();
|
||||
|
||||
@@ -1229,5 +1231,49 @@ namespace Emby.Server.Implementations
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await DisposeAsyncCore().ConfigureAwait(false);
|
||||
Dispose(false);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to perform asynchronous cleanup of managed resources or for cascading calls to <see cref="DisposeAsync"/>.
|
||||
/// </summary>
|
||||
/// <returns>A ValueTask.</returns>
|
||||
protected virtual async ValueTask DisposeAsyncCore()
|
||||
{
|
||||
var type = GetType();
|
||||
|
||||
Logger.LogInformation("Disposing {Type}", type.Name);
|
||||
|
||||
foreach (var (part, _) in _disposableParts)
|
||||
{
|
||||
var partType = part.GetType();
|
||||
if (partType == type)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Logger.LogInformation("Disposing {Type}", partType.Name);
|
||||
|
||||
try
|
||||
{
|
||||
part.Dispose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error disposing {Type}", partType.Name);
|
||||
}
|
||||
}
|
||||
|
||||
// used for closing websockets
|
||||
foreach (var session in _sessionManager.Sessions)
|
||||
{
|
||||
await session.DisposeAsync().ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4934,6 +4934,7 @@ SELECT key FROM UserDatas WHERE isFavorite=@IsFavorite AND userId=@UserId)
|
||||
AND Type = @InternalPersonType)");
|
||||
statement?.TryBind("@IsFavorite", query.IsFavorite.Value);
|
||||
statement?.TryBind("@InternalPersonType", typeof(Person).FullName);
|
||||
statement?.TryBind("@UserId", query.User.InternalId);
|
||||
}
|
||||
|
||||
if (!query.ItemId.Equals(default))
|
||||
@@ -4988,11 +4989,6 @@ AND Type = @InternalPersonType)");
|
||||
statement?.TryBind("@NameContains", "%" + query.NameContains + "%");
|
||||
}
|
||||
|
||||
if (query.User != null)
|
||||
{
|
||||
statement?.TryBind("@UserId", query.User.InternalId);
|
||||
}
|
||||
|
||||
return whereClauses;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="6.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.6" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="6.0.7" />
|
||||
<PackageReference Include="Mono.Nat" Version="3.0.3" />
|
||||
<PackageReference Include="prometheus-net.DotNetRuntime" Version="4.2.4" />
|
||||
<PackageReference Include="SQLitePCL.pretty.netstandard" Version="3.1.0" />
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
/// <summary>
|
||||
/// Class WebSocketConnection.
|
||||
/// </summary>
|
||||
public class WebSocketConnection : IWebSocketConnection, IDisposable
|
||||
public class WebSocketConnection : IWebSocketConnection
|
||||
{
|
||||
/// <summary>
|
||||
/// The logger.
|
||||
@@ -36,6 +36,8 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
/// </summary>
|
||||
private readonly WebSocket _socket;
|
||||
|
||||
private bool _disposed = false;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="WebSocketConnection" /> class.
|
||||
/// </summary>
|
||||
@@ -244,10 +246,39 @@ namespace Emby.Server.Implementations.HttpServer
|
||||
/// <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)
|
||||
{
|
||||
_socket.Dispose();
|
||||
}
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
await DisposeAsyncCore().ConfigureAwait(false);
|
||||
Dispose(false);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to perform asynchronous cleanup of managed resources or for cascading calls to <see cref="DisposeAsync"/>.
|
||||
/// </summary>
|
||||
/// <returns>A ValueTask.</returns>
|
||||
protected virtual async ValueTask DisposeAsyncCore()
|
||||
{
|
||||
if (_socket.State == WebSocketState.Open)
|
||||
{
|
||||
await _socket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "System Shutdown", CancellationToken.None).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
_socket.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2453,6 +2453,12 @@ namespace Emby.Server.Implementations.Library
|
||||
return RootFolder;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void QueueLibraryScan()
|
||||
{
|
||||
_taskManager.QueueScheduledTask<RefreshMediaLibraryTask>();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int? GetSeasonNumberFromPath(string path)
|
||||
=> SeasonPathParser.Parse(path, true, true).SeasonNumber;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"Albums": "ألبومات",
|
||||
"Albums": "البومات",
|
||||
"AppDeviceValues": "تطبيق: {0}, جهاز: {1}",
|
||||
"Application": "تطبيق",
|
||||
"Artists": "الفنانين",
|
||||
@@ -92,22 +92,22 @@
|
||||
"ValueHasBeenAddedToLibrary": "تمت اضافت {0} إلى مكتبة الوسائط",
|
||||
"ValueSpecialEpisodeName": "حلقه خاصه - {0}",
|
||||
"VersionNumber": "النسخة {0}",
|
||||
"TaskCleanCacheDescription": "يحذف ملفات ذاكرة التخزين المؤقت التي لم يعد النظام بحاجة إليها.",
|
||||
"TaskCleanCache": "احذف مجلد ذاكرة التخزين المؤقت",
|
||||
"TaskCleanCacheDescription": "يحذف الملفات المؤقتة التي لم يعد النظام بحاجة إليها.",
|
||||
"TaskCleanCache": "احذف ما بمجلد الملفات المؤقتة",
|
||||
"TasksChannelsCategory": "قنوات الإنترنت",
|
||||
"TasksLibraryCategory": "مكتبة",
|
||||
"TasksMaintenanceCategory": "صيانة",
|
||||
"TaskRefreshLibraryDescription": "يقوم بفصح مكتبة الوسائط الخاصة بك بحثًا عن ملفات جديدة وتحديث البيانات الوصفية.",
|
||||
"TaskRefreshLibraryDescription": "يفصح مكتبة الوسائط الخاصة بك بحثًا عن ملفات جديدة، ومن ثم يتحدث البيانات الوصفية.",
|
||||
"TaskRefreshLibrary": "افحص مكتبة الوسائط",
|
||||
"TaskRefreshChapterImagesDescription": "يقوم بانشاء صور مصغرة لمقاطع الفيديو التي تحتوي على فصول.",
|
||||
"TaskRefreshChapterImagesDescription": "يُنشئ صور مصغرة لمقاطع الفيديو التي تحتوي على فصول.",
|
||||
"TaskRefreshChapterImages": "استخراج صور الفصل",
|
||||
"TasksApplicationCategory": "تطبيق",
|
||||
"TaskDownloadMissingSubtitlesDescription": "يقوم بالبحث في الإنترنت على الترجمات المفقودة إستنادا على البيانات الوصفية.",
|
||||
"TaskDownloadMissingSubtitles": "تحميل الترجمات المفقودة",
|
||||
"TaskRefreshChannelsDescription": "يقوم بتحديث معلومات قنوات الإنترنت.",
|
||||
"TaskDownloadMissingSubtitlesDescription": "يبحث في الإنترنت على الترجمات الناقصة استنادا على البيانات الوصفية.",
|
||||
"TaskDownloadMissingSubtitles": "تحميل الترجمات الناقصة",
|
||||
"TaskRefreshChannelsDescription": "يحدث معلومات قنوات الإنترنت.",
|
||||
"TaskRefreshChannels": "إعادة تحديث القنوات",
|
||||
"TaskCleanTranscodeDescription": "يقوم بحذف ملفات الترميز الأقدم من يوم واحد.",
|
||||
"TaskCleanTranscode": "حذف سجلات الترميز",
|
||||
"TaskCleanTranscodeDescription": "يحذف ملفات الترميز الأقدم من يوم واحد.",
|
||||
"TaskCleanTranscode": "حذف ما بمجلد الترميز",
|
||||
"TaskUpdatePluginsDescription": "تحميل وتثبيت الإضافات التي تم تفعيل التحديث التلقائي لها.",
|
||||
"TaskUpdatePlugins": "تحديث الإضافات",
|
||||
"TaskRefreshPeopleDescription": "يقوم بتحديث البيانات الوصفية للممثلين والمخرجين في مكتبة الوسائط الخاصة بك.",
|
||||
@@ -116,12 +116,12 @@
|
||||
"TaskCleanLogs": "حذف مسار السجل",
|
||||
"TaskCleanActivityLogDescription": "يحذف سجل الأنشطة الأقدم من الوقت الذي تم تحديده.",
|
||||
"TaskCleanActivityLog": "حذف سجل الأنشطة",
|
||||
"Default": "إفتراضي",
|
||||
"Default": "افتراضي",
|
||||
"Undefined": "غير معرف",
|
||||
"Forced": "ملحقة",
|
||||
"TaskOptimizeDatabaseDescription": "يضغط قاعدة البيانات ويقتطع المساحة الحرة. تشغيل هذه المهمة بعد فحص المكتبة أو إجراء تغييرات أخرى تتضمن تعديلات في قاعدة البيانات قد تؤدي إلى تحسين الأداء.",
|
||||
"TaskOptimizeDatabase": "تحسين قاعدة البيانات",
|
||||
"TaskKeyframeExtractorDescription": "يقوم باستخراج الإطارات الرئيسيه من ملفات الفيديو لكي ينشئ قوائم تشغيل بث HTTP المباشر. هذه المهمه قد تستمر لاوقات طويلة.",
|
||||
"TaskKeyframeExtractorDescription": "يستخرج الإطارات الرئيسية من ملفات الفيديو لكي ينشئ قوائم تشغيل بث HTTP المباشر. قد تستمر هذه العملية لوقت طويل.",
|
||||
"TaskKeyframeExtractor": "مستخرج الإطار الرئيسي",
|
||||
"External": "خارجي"
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
"Default": "Standard",
|
||||
"TaskOptimizeDatabaseDescription": "Komprimiert die Datenbank und trimmt den freien Speicherplatz. Die Ausführung dieser Aufgabe nach dem Scannen der Bibliothek oder nach anderen Änderungen, die Datenbankänderungen implizieren, kann die Leistung verbessern.",
|
||||
"TaskOptimizeDatabase": "Datenbank optimieren",
|
||||
"TaskKeyframeExtractorDescription": "Extrahiere Keyframes aus Videodateien, um präzisere HLS-Playlisten zu erzeugen. Diese Aufgabe kann sehr lange dauern.",
|
||||
"TaskKeyframeExtractorDescription": "Extrahiere Keyframes aus Videodateien, um präzisere HLS-Playlisten zu erzeugen. Dieser Vorgang kann sehr lange dauern.",
|
||||
"TaskKeyframeExtractor": "Keyframe Extraktor",
|
||||
"External": "Extern"
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"Artists": "Artistes",
|
||||
"AuthenticationSucceededWithUserName": "{0} authentifié avec succès",
|
||||
"Books": "Livres",
|
||||
"CameraImageUploadedFrom": "Une photo a été chargée depuis {0}",
|
||||
"CameraImageUploadedFrom": "Une photo a été téléversée depuis {0}",
|
||||
"Channels": "Chaînes",
|
||||
"ChapterNameValue": "Chapitre {0}",
|
||||
"Collections": "Collections",
|
||||
@@ -42,13 +42,13 @@
|
||||
"MusicVideos": "Clips musicaux",
|
||||
"NameInstallFailed": "{0} échec de l'installation",
|
||||
"NameSeasonNumber": "Saison {0}",
|
||||
"NameSeasonUnknown": "Saison Inconnue",
|
||||
"NameSeasonUnknown": "Saison inconnue",
|
||||
"NewVersionIsAvailable": "Une nouvelle version de Jellyfin Serveur est disponible au téléchargement.",
|
||||
"NotificationOptionApplicationUpdateAvailable": "Mise à jour de l'application disponible",
|
||||
"NotificationOptionApplicationUpdateInstalled": "Mise à jour de l'application installée",
|
||||
"NotificationOptionAudioPlayback": "Lecture audio démarrée",
|
||||
"NotificationOptionAudioPlaybackStopped": "Lecture audio arrêtée",
|
||||
"NotificationOptionCameraImageUploaded": "L'image de l'appareil photo a été transférée",
|
||||
"NotificationOptionCameraImageUploaded": "L'image de l'appareil photo a été téléversée",
|
||||
"NotificationOptionInstallationFailed": "Échec de l'installation",
|
||||
"NotificationOptionNewLibraryContent": "Nouveau contenu ajouté",
|
||||
"NotificationOptionPluginError": "Erreur d'extension",
|
||||
@@ -71,7 +71,7 @@
|
||||
"ScheduledTaskStartedWithName": "{0} a démarré",
|
||||
"ServerNameNeedsToBeRestarted": "{0} doit être redémarré",
|
||||
"Shows": "Séries",
|
||||
"Songs": "Chansons",
|
||||
"Songs": "Titres",
|
||||
"StartupEmbyServerIsLoading": "Le serveur Jellyfin est en cours de chargement. Veuillez réessayer dans quelques instants.",
|
||||
"SubtitleDownloadFailureForItem": "Le téléchargement des sous-titres pour {0} a échoué.",
|
||||
"SubtitleDownloadFailureFromForItem": "Échec du téléchargement des sous-titres depuis {0} pour {1}",
|
||||
@@ -92,34 +92,34 @@
|
||||
"ValueHasBeenAddedToLibrary": "{0} a été ajouté à votre médiathèque",
|
||||
"ValueSpecialEpisodeName": "Spécial - {0}",
|
||||
"VersionNumber": "Version {0}",
|
||||
"TasksChannelsCategory": "Chaines en ligne",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Recherche les sous-titres manquants sur internet en se basant sur la configuration des métadonnées.",
|
||||
"TasksChannelsCategory": "Chaînes en ligne",
|
||||
"TaskDownloadMissingSubtitlesDescription": "Recherche les sous-titres manquants sur Internet en se basant sur la configuration des métadonnées.",
|
||||
"TaskDownloadMissingSubtitles": "Télécharger les sous-titres manquants",
|
||||
"TaskRefreshChannelsDescription": "Rafraîchit les informations des chaines en ligne.",
|
||||
"TaskRefreshChannels": "Rafraîchir les chaines",
|
||||
"TaskRefreshChannelsDescription": "Actualise les informations des chaînes en ligne.",
|
||||
"TaskRefreshChannels": "Actualiser les chaînes",
|
||||
"TaskCleanTranscodeDescription": "Supprime les fichiers transcodés de plus d'un jour.",
|
||||
"TaskCleanTranscode": "Nettoyer les dossier des transcodages",
|
||||
"TaskCleanTranscode": "Nettoyer le dossier des transcodages",
|
||||
"TaskUpdatePluginsDescription": "Télécharge et installe les mises à jours des extensions configurées pour être mises à jour automatiquement.",
|
||||
"TaskUpdatePlugins": "Mettre à jour les extensions",
|
||||
"TaskRefreshPeopleDescription": "Met à jour les métadonnées pour les acteurs et réalisateurs dans votre bibliothèque.",
|
||||
"TaskRefreshPeople": "Rafraîchir les acteurs",
|
||||
"TaskRefreshPeopleDescription": "Met à jour les métadonnées pour les acteurs et réalisateurs dans votre médiathèque.",
|
||||
"TaskRefreshPeople": "Actualiser les acteurs",
|
||||
"TaskCleanLogsDescription": "Supprime les journaux de plus de {0} jours.",
|
||||
"TaskCleanLogs": "Nettoyer le répertoire des journaux",
|
||||
"TaskRefreshLibraryDescription": "Scanne votre médiathèque pour trouver les nouveaux fichiers et rafraîchit les métadonnées.",
|
||||
"TaskRefreshLibraryDescription": "Scanne votre médiathèque pour trouver les nouveaux fichiers et actualise les métadonnées.",
|
||||
"TaskRefreshLibrary": "Scanner la médiathèque",
|
||||
"TaskRefreshChapterImagesDescription": "Crée des vignettes pour les vidéos ayant des chapitres.",
|
||||
"TaskRefreshChapterImages": "Extraire les images de chapitre",
|
||||
"TaskCleanCacheDescription": "Supprime les fichiers de cache dont le système n'a plus besoin.",
|
||||
"TaskCleanCache": "Vider le répertoire cache",
|
||||
"TasksApplicationCategory": "Application",
|
||||
"TasksLibraryCategory": "Bibliothèque",
|
||||
"TasksLibraryCategory": "Médiathèque",
|
||||
"TasksMaintenanceCategory": "Maintenance",
|
||||
"TaskCleanActivityLogDescription": "Supprime les entrées du journal d'activité antérieures à l'âge configuré.",
|
||||
"TaskCleanActivityLog": "Nettoyer le journal d'activité",
|
||||
"Undefined": "Non défini",
|
||||
"Forced": "Forcé",
|
||||
"Default": "Par défaut",
|
||||
"TaskOptimizeDatabaseDescription": "Réduit les espaces vides/inutiles et compacte la base de données. Utiliser cette fonction après une mise à jour de la bibliothèque ou toute autre modification de la base de données peut améliorer les performances du serveur.",
|
||||
"TaskOptimizeDatabaseDescription": "Réduit les espaces vides ou inutiles et compacte la base de données. Utiliser cette fonction après une mise à jour de la médiathèque ou toute autre modification de la base de données peut améliorer les performances du serveur.",
|
||||
"TaskOptimizeDatabase": "Optimiser la base de données",
|
||||
"TaskKeyframeExtractorDescription": "Extrait les images clés des fichiers vidéo pour créer des listes de lecture HLS plus précises. Cette tâche peut durer très longtemps.",
|
||||
"TaskKeyframeExtractor": "Extracteur d'image clé",
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
"MixedContent": "Mixed content",
|
||||
"Movies": "Filmai",
|
||||
"Music": "Muzika",
|
||||
"MusicVideos": "Muzikiniai klipai",
|
||||
"MusicVideos": "Muzikiniai vaizdo įrašai",
|
||||
"NameInstallFailed": "{0} diegimo klaida",
|
||||
"NameSeasonNumber": "Sezonas {0}",
|
||||
"NameSeasonUnknown": "Sezonas neatpažintas",
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
"NotificationOptionVideoPlayback": "Ulangmain video bermula",
|
||||
"NotificationOptionVideoPlaybackStopped": "Ulangmain video dihentikan",
|
||||
"Photos": "Gambar-gambar",
|
||||
"Playlists": "Senarai main",
|
||||
"Playlists": "Senarai ulangmain",
|
||||
"Plugin": "Plugin",
|
||||
"PluginInstalledWithName": "{0} telah dipasang",
|
||||
"PluginUninstalledWithName": "{0} telah dinyahpasang",
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"ItemRemovedWithName": "{0} - изъято из медиатеки",
|
||||
"LabelIpAddressValue": "IP-адрес: {0}",
|
||||
"LabelRunningTimeValue": "Длительность: {0}",
|
||||
"Latest": "Крайнее",
|
||||
"Latest": "Новое",
|
||||
"MessageApplicationUpdated": "Jellyfin Server был обновлён",
|
||||
"MessageApplicationUpdatedTo": "Jellyfin Server был обновлён до {0}",
|
||||
"MessageNamedServerConfigurationUpdatedWithValue": "Конфигурация сервера (раздел {0}) была обновлена",
|
||||
|
||||
@@ -120,5 +120,7 @@
|
||||
"Default": "Подразумевано",
|
||||
"TaskOptimizeDatabase": "Оптимизуј датабазу",
|
||||
"TaskOptimizeDatabaseDescription": "Сажима базу података и скраћује слободан простор. Покретање овог задатка након скенирања библиотеке или других промена које подразумевају измене базе података које могу побољшати перформансе.",
|
||||
"External": "Спољно"
|
||||
"External": "Спољно",
|
||||
"TaskKeyframeExtractorDescription": "Екстрактује кљулне сличице из видео датотека да би креирао више преицзну HLS плеј-листу. Овај задатак може да потраје дуже време.",
|
||||
"TaskKeyframeExtractor": "Екстрактор кључних сличица"
|
||||
}
|
||||
|
||||
@@ -10,19 +10,19 @@
|
||||
"ItemAddedWithName": "{0} додано до медіатеки",
|
||||
"HeaderNextUp": "Наступний",
|
||||
"HeaderLiveTV": "Ефірне ТБ",
|
||||
"HeaderFavoriteSongs": "Улюблені пісні",
|
||||
"HeaderFavoriteShows": "Улюблені шоу",
|
||||
"HeaderFavoriteEpisodes": "Улюблені серії",
|
||||
"HeaderFavoriteArtists": "Улюблені виконавці",
|
||||
"HeaderFavoriteAlbums": "Улюблені альбоми",
|
||||
"HeaderFavoriteSongs": "Обрані пісні",
|
||||
"HeaderFavoriteShows": "Обрані шоу",
|
||||
"HeaderFavoriteEpisodes": "Обрані епізоди",
|
||||
"HeaderFavoriteArtists": "Обрані виконавці",
|
||||
"HeaderFavoriteAlbums": "Обрані альбоми",
|
||||
"HeaderContinueWatching": "Продовжити перегляд",
|
||||
"HeaderAlbumArtists": "Виконавці альбому",
|
||||
"Genres": "Жанри",
|
||||
"Folders": "Каталоги",
|
||||
"Favorites": "Улюблені",
|
||||
"Favorites": "Обрані",
|
||||
"DeviceOnlineWithName": "Пристрій {0} підключився",
|
||||
"DeviceOfflineWithName": "Пристрій {0} відключився",
|
||||
"Collections": "Колекції",
|
||||
"Collections": "Добірки",
|
||||
"ChapterNameValue": "Розділ {0}",
|
||||
"Channels": "Канали",
|
||||
"CameraImageUploadedFrom": "Нова фотографія завантажена з {0}",
|
||||
@@ -119,7 +119,7 @@
|
||||
"Undefined": "Не визначено",
|
||||
"Default": "За замовчуванням",
|
||||
"TaskOptimizeDatabase": "Оптимізувати базу даних",
|
||||
"TaskOptimizeDatabaseDescription": "Стиснення бази даних та збільшення вільного простору. Виконання цього завдання після сканування бібліотеки або внесення інших змін, які передбачають модифікацію бази даних, може покращити продуктивність.",
|
||||
"TaskOptimizeDatabaseDescription": "Стискає базу даних та збільшує вільний простір. Виконання цього завдання після сканування медіатеки або внесення інших змін, які передбачають модифікацію бази даних може покращити продуктивність.",
|
||||
"TaskKeyframeExtractorDescription": "Витягує ключові кадри з відеофайлів для створення більш точних списків відтворення HLS. Це завдання може виконуватися протягом тривалого часу.",
|
||||
"TaskKeyframeExtractor": "Екстрактор ключових кадрів",
|
||||
"External": "Зовнішній"
|
||||
|
||||
@@ -14,7 +14,7 @@ using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Emby.Server.Implementations.Session
|
||||
{
|
||||
public sealed class WebSocketController : ISessionController, IDisposable
|
||||
public sealed class WebSocketController : ISessionController, IAsyncDisposable, IDisposable
|
||||
{
|
||||
private readonly ILogger<WebSocketController> _logger;
|
||||
private readonly ISessionManager _sessionManager;
|
||||
@@ -99,6 +99,23 @@ namespace Emby.Server.Implementations.Session
|
||||
foreach (var socket in _sockets)
|
||||
{
|
||||
socket.Closed -= OnConnectionClosed;
|
||||
socket.Dispose();
|
||||
}
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var socket in _sockets)
|
||||
{
|
||||
socket.Closed -= OnConnectionClosed;
|
||||
await socket.DisposeAsync().ConfigureAwait(false);
|
||||
}
|
||||
|
||||
_disposed = true;
|
||||
|
||||
Reference in New Issue
Block a user