aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations')
-rw-r--r--Emby.Server.Implementations/Data/SqliteItemRepository.cs21
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs23
-rw-r--r--Emby.Server.Implementations/Localization/Core/be.json127
-rw-r--r--Emby.Server.Implementations/Localization/Core/gsw.json12
-rw-r--r--Emby.Server.Implementations/Plugins/PluginManager.cs53
5 files changed, 204 insertions, 32 deletions
diff --git a/Emby.Server.Implementations/Data/SqliteItemRepository.cs b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
index bc703fe90d..602d2a8538 100644
--- a/Emby.Server.Implementations/Data/SqliteItemRepository.cs
+++ b/Emby.Server.Implementations/Data/SqliteItemRepository.cs
@@ -4477,6 +4477,24 @@ namespace Emby.Server.Implementations.Data
}
}
+ if (query.IncludeInheritedTags.Length > 0)
+ {
+ var paramName = "@IncludeInheritedTags";
+ if (statement is null)
+ {
+ int index = 0;
+ string includedTags = string.Join(',', query.IncludeInheritedTags.Select(_ => paramName + index++));
+ whereClauses.Add("((select CleanValue from ItemValues where ItemId=Guid and Type=6 and cleanvalue in (" + includedTags + ")) is not null)");
+ }
+ else
+ {
+ for (int index = 0; index < query.IncludeInheritedTags.Length; index++)
+ {
+ statement.TryBind(paramName + index, GetCleanValue(query.IncludeInheritedTags[index]));
+ }
+ }
+ }
+
if (query.SeriesStatuses.Length > 0)
{
var statuses = new List<string>();
@@ -5440,6 +5458,9 @@ AND Type = @InternalPersonType)");
list.AddRange(inheritedTags.Select(i => (6, i)));
+ // Remove all invalid values.
+ list.RemoveAll(i => string.IsNullOrEmpty(i.Item2));
+
return list;
}
diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs
index e874990da1..066afb956b 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs
@@ -137,32 +137,33 @@ namespace Emby.Server.Implementations.LiveTv.Listings
private static ProgramInfo GetProgramInfo(XmlTvProgram program, ListingsProviderInfo info)
{
- string episodeTitle = program.Episode?.Title;
+ string episodeTitle = program.Episode.Title;
+ var programCategories = program.Categories.Where(c => !string.IsNullOrWhiteSpace(c)).ToList();
var programInfo = new ProgramInfo
{
ChannelId = program.ChannelId,
EndDate = program.EndDate.UtcDateTime,
- EpisodeNumber = program.Episode?.Episode,
+ EpisodeNumber = program.Episode.Episode,
EpisodeTitle = episodeTitle,
- Genres = program.Categories,
+ Genres = programCategories,
StartDate = program.StartDate.UtcDateTime,
Name = program.Title,
Overview = program.Description,
ProductionYear = program.CopyrightDate?.Year,
- SeasonNumber = program.Episode?.Series,
- IsSeries = program.Episode is not null,
+ SeasonNumber = program.Episode.Series,
+ IsSeries = program.Episode.Series is not null,
IsRepeat = program.IsPreviouslyShown && !program.IsNew,
IsPremiere = program.Premiere is not null,
- IsKids = program.Categories.Any(c => info.KidsCategories.Contains(c, StringComparison.OrdinalIgnoreCase)),
- IsMovie = program.Categories.Any(c => info.MovieCategories.Contains(c, StringComparison.OrdinalIgnoreCase)),
- IsNews = program.Categories.Any(c => info.NewsCategories.Contains(c, StringComparison.OrdinalIgnoreCase)),
- IsSports = program.Categories.Any(c => info.SportsCategories.Contains(c, StringComparison.OrdinalIgnoreCase)),
+ IsKids = programCategories.Any(c => info.KidsCategories.Contains(c, StringComparison.OrdinalIgnoreCase)),
+ IsMovie = programCategories.Any(c => info.MovieCategories.Contains(c, StringComparison.OrdinalIgnoreCase)),
+ IsNews = programCategories.Any(c => info.NewsCategories.Contains(c, StringComparison.OrdinalIgnoreCase)),
+ IsSports = programCategories.Any(c => info.SportsCategories.Contains(c, StringComparison.OrdinalIgnoreCase)),
ImageUrl = string.IsNullOrEmpty(program.Icon?.Source) ? null : program.Icon.Source,
HasImage = !string.IsNullOrEmpty(program.Icon?.Source),
OfficialRating = string.IsNullOrEmpty(program.Rating?.Value) ? null : program.Rating.Value,
CommunityRating = program.StarRating,
- SeriesId = program.Episode is null ? null : program.Title?.GetMD5().ToString("N", CultureInfo.InvariantCulture)
+ SeriesId = program.Episode.Episode is null ? null : program.Title?.GetMD5().ToString("N", CultureInfo.InvariantCulture)
};
if (string.IsNullOrWhiteSpace(program.ProgramId))
@@ -243,7 +244,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
{
Id = c.Id,
Name = c.DisplayName,
- ImageUrl = string.IsNullOrEmpty(c.Icon.Source) ? null : c.Icon.Source,
+ ImageUrl = string.IsNullOrEmpty(c.Icon?.Source) ? null : c.Icon.Source,
Number = string.IsNullOrWhiteSpace(c.Number) ? c.Id : c.Number
}).ToList();
}
diff --git a/Emby.Server.Implementations/Localization/Core/be.json b/Emby.Server.Implementations/Localization/Core/be.json
index 56c4e7d39d..3af124678f 100644
--- a/Emby.Server.Implementations/Localization/Core/be.json
+++ b/Emby.Server.Implementations/Localization/Core/be.json
@@ -1,4 +1,127 @@
{
- "Sync": "Сінхранізацыя",
- "Playlists": "Плэйліст"
+ "Sync": "Сінхранізаваць",
+ "Playlists": "Плэйлісты",
+ "Latest": "Апошні",
+ "LabelIpAddressValue": "IP-адрас: {0}",
+ "ItemAddedWithName": "{0} быў дададзены ў бібліятэку",
+ "MessageApplicationUpdated": "Сервер Jellyfin абноўлены",
+ "NotificationOptionApplicationUpdateInstalled": "Абнаўленне прыкладання ўсталявана",
+ "PluginInstalledWithName": "{0} быў усталяваны",
+ "UserCreatedWithName": "Карыстальнік {0} быў створаны",
+ "Albums": "Альбомы",
+ "Application": "Прыкладанне",
+ "AuthenticationSucceededWithUserName": "{0} паспяхова аўтэнтыфікаваны",
+ "Channels": "Каналы",
+ "ChapterNameValue": "Раздзел {0}",
+ "Collections": "Калекцыі",
+ "Default": "Па змаўчанні",
+ "FailedLoginAttemptWithUserName": "Няўдалая спроба ўваходу з {0}",
+ "Folders": "Папкі",
+ "Favorites": "Абранае",
+ "External": "Знешні",
+ "Genres": "Жанры",
+ "HeaderContinueWatching": "Працягнуць прагляд",
+ "HeaderFavoriteAlbums": "Абраныя альбомы",
+ "HeaderFavoriteEpisodes": "Абраныя серыі",
+ "HeaderFavoriteShows": "Абраныя шоу",
+ "HeaderFavoriteSongs": "Абраныя песні",
+ "HeaderLiveTV": "Прамы эфір",
+ "HeaderAlbumArtists": "Выканаўцы альбома",
+ "LabelRunningTimeValue": "Працягласць: {0}",
+ "HomeVideos": "Хатнія відэа",
+ "ItemRemovedWithName": "{0} быў выдалены з бібліятэкі",
+ "MessageApplicationUpdatedTo": "Сервер Jellyfin абноўлены да {0}",
+ "Movies": "Фільмы",
+ "Music": "Музыка",
+ "MusicVideos": "Музычныя кліпы",
+ "NameInstallFailed": "Устаноўка {0} не атрымалася",
+ "NameSeasonNumber": "Сезон {0}",
+ "NotificationOptionApplicationUpdateAvailable": "Даступна абнаўленне прыкладання",
+ "NotificationOptionPluginInstalled": "Плагін усталяваны",
+ "NotificationOptionPluginUpdateInstalled": "Абнаўленне плагіна усталявана",
+ "NotificationOptionServerRestartRequired": "Патрабуецца перазапуск сервера",
+ "Photos": "Фатаграфіі",
+ "Plugin": "Плагін",
+ "PluginUninstalledWithName": "{0} быў выдалены",
+ "PluginUpdatedWithName": "{0} быў абноўлены",
+ "ProviderValue": "Пастаўшчык: {0}",
+ "Songs": "Песні",
+ "System": "Сістэма",
+ "User": "Карыстальнік",
+ "UserDeletedWithName": "Карыстальнік {0} быў выдалены",
+ "UserDownloadingItemWithValues": "{0} спампоўваецца {1}",
+ "TaskOptimizeDatabase": "Аптымізаваць базу дадзеных",
+ "Artists": "Выканаўцы",
+ "UserOfflineFromDevice": "{0} адключыўся ад {1}",
+ "UserPolicyUpdatedWithName": "Палітыка карыстальніка абноўлена для {0}",
+ "TaskCleanActivityLogDescription": "Выдаляе старэйшыя за зададзены ўзрост запісы ў журнале актыўнасці.",
+ "TaskRefreshChapterImagesDescription": "Стварае мініяцюры для відэа, якія маюць раздзелы.",
+ "TaskCleanLogsDescription": "Выдаляе файлы журналу, якім больш за {0} дзён.",
+ "TaskUpdatePluginsDescription": "Спампоўвае і ўсталёўвае абнаўленні для плагінаў, якія настроены на аўтаматычнае абнаўленне.",
+ "TaskRefreshChannelsDescription": "Абнаўляе інфармацыю аб інтэрнэт-канале.",
+ "TaskDownloadMissingSubtitlesDescription": "Шукае ў інтэрнэце адсутныя субтытры на аснове канфігурацыі метададзеных.",
+ "TaskOptimizeDatabaseDescription": "Ушчыльняе базу дадзеных і скарачае вольную прастору. Выкананне гэтай задачы пасля сканавання бібліятэкі або ўнясення іншых змяненняў, якія прадугледжваюць мадыфікацыю базы дадзеных, можа палепшыць прадукцыйнасць.",
+ "TaskKeyframeExtractor": "Экстрактар ключавых кадраў",
+ "TasksApplicationCategory": "Прыкладанне",
+ "AppDeviceValues": "Прыкладанне: {0}, Прылада: {1}",
+ "Books": "Кнігі",
+ "CameraImageUploadedFrom": "Новая выява камеры была загружана з {0}",
+ "DeviceOfflineWithName": "{0} адключыўся",
+ "DeviceOnlineWithName": "{0} падлучаны",
+ "Forced": "Прымусова",
+ "HeaderRecordingGroups": "Групы запісаў",
+ "HeaderNextUp": "Наступнае",
+ "HeaderFavoriteArtists": "Абраныя выканаўцы",
+ "HearingImpaired": "Са слабым слыхам",
+ "Inherit": "Атрымаць у спадчыну",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Канфігурацыя сервера {0} абноўлена",
+ "MessageServerConfigurationUpdated": "Канфігурацыя сервера абноўлена",
+ "MixedContent": "Змешаны змест",
+ "NameSeasonUnknown": "Невядомы сезон",
+ "NotificationOptionInstallationFailed": "Збой усталёўкі",
+ "NewVersionIsAvailable": "Новая версія сервера Jellyfin даступная для cпампоўкі.",
+ "NotificationOptionCameraImageUploaded": "Выява камеры запампавана",
+ "NotificationOptionAudioPlaybackStopped": "Прайграванне аўдыё спынена",
+ "NotificationOptionAudioPlayback": "Прайграванне аўдыё пачалося",
+ "NotificationOptionNewLibraryContent": "Дададзены новы кантэнт",
+ "NotificationOptionPluginError": "Збой плагіна",
+ "NotificationOptionPluginUninstalled": "Плагін выдалены",
+ "NotificationOptionTaskFailed": "Збой запланаванага задання",
+ "NotificationOptionUserLockedOut": "Карыстальнік заблакіраваны",
+ "NotificationOptionVideoPlayback": "Пачалося прайграванне відэа",
+ "NotificationOptionVideoPlaybackStopped": "Прайграванне відэа спынена",
+ "ScheduledTaskFailedWithName": "{0} не атрымалася",
+ "ScheduledTaskStartedWithName": "{0} пачалося",
+ "ServerNameNeedsToBeRestarted": "{0} трэба перазапусціць",
+ "Shows": "Шоу",
+ "StartupEmbyServerIsLoading": "Jellyfin Server загружаецца. Калі ласка, паўтарыце спробу крыху пазней.",
+ "SubtitleDownloadFailureFromForItem": "Не атрымалася спампаваць субтытры з {0} для {1}",
+ "TvShows": "ТБ-шоу",
+ "Undefined": "Нявызначана",
+ "UserLockedOutWithName": "Карыстальнік {0} быў заблакіраваны",
+ "UserOnlineFromDevice": "{0} падключаны з {1}",
+ "UserPasswordChangedWithName": "Пароль быў зменены для карыстальніка {0}",
+ "UserStartedPlayingItemWithValues": "{0} грае {1} на {2}",
+ "UserStoppedPlayingItemWithValues": "{0} скончыў прайграванне {1} на {2}",
+ "ValueHasBeenAddedToLibrary": "{0} быў дададзены ў вашу медыятэку",
+ "ValueSpecialEpisodeName": "Спецэпізод - {0}",
+ "VersionNumber": "Версія {0}",
+ "TasksMaintenanceCategory": "Абслугоўванне",
+ "TasksLibraryCategory": "Медыятэка",
+ "TasksChannelsCategory": "Інтэрнэт-каналы",
+ "TaskCleanActivityLog": "Ачысціць журнал актыўнасці",
+ "TaskCleanCache": "Ачысціць кэш",
+ "TaskCleanCacheDescription": "Выдаляе файлы кэша, якія больш не патрэбныя сістэме.",
+ "TaskRefreshChapterImages": "Выняць выявы раздзелаў",
+ "TaskRefreshLibrary": "Сканіраваць медыятэку",
+ "TaskRefreshLibraryDescription": "Сканіруе вашу медыятэку на наяўнасць новых файлаў і абнаўляе метададзеныя.",
+ "TaskCleanLogs": "Ачысціць часопіс",
+ "TaskRefreshPeople": "Абнавіць людзей",
+ "TaskRefreshPeopleDescription": "Абнаўленне метаданых для акцёраў і рэжысёраў у вашай медыятэцы.",
+ "TaskUpdatePlugins": "Абнавіць плагіны",
+ "TaskCleanTranscode": "Ачысціць каталог перакадзіравання",
+ "TaskCleanTranscodeDescription": "Выдаляе перакадзіраваныя файлы, старэйшыя за адзін дзень.",
+ "TaskRefreshChannels": "Абнавіць каналы",
+ "TaskDownloadMissingSubtitles": "Спампаваць адсутныя субтытры",
+ "TaskKeyframeExtractorDescription": "Выдае ключавыя кадры з відэафайлаў для стварэння больш дакладных спісаў прайгравання HLS. Гэта задача можа працаваць у працягу доўгага часу."
}
diff --git a/Emby.Server.Implementations/Localization/Core/gsw.json b/Emby.Server.Implementations/Localization/Core/gsw.json
index bd8cec710b..ac9da1dd12 100644
--- a/Emby.Server.Implementations/Localization/Core/gsw.json
+++ b/Emby.Server.Implementations/Localization/Core/gsw.json
@@ -1,7 +1,7 @@
{
"Albums": "Alben",
"AppDeviceValues": "App: {0}, Gerät: {1}",
- "Application": "Anwendung",
+ "Application": "Applikation",
"Artists": "Künstler",
"AuthenticationSucceededWithUserName": "{0} hat sich angemeldet",
"Books": "Bücher",
@@ -14,7 +14,7 @@
"FailedLoginAttemptWithUserName": "Fehlgeschlagener Anmeldeversuch von {0}",
"Favorites": "Favoriten",
"Folders": "Ordner",
- "Genres": "Genres",
+ "Genres": "Genre",
"HeaderAlbumArtists": "Album-Künstler",
"HeaderContinueWatching": "weiter schauen",
"HeaderFavoriteAlbums": "Lieblingsalben",
@@ -49,7 +49,7 @@
"NotificationOptionAudioPlayback": "Audiowedergab gstartet",
"NotificationOptionAudioPlaybackStopped": "Audiwedergab gstoppt",
"NotificationOptionCameraImageUploaded": "Foti ueglade",
- "NotificationOptionInstallationFailed": "Installationsfehler",
+ "NotificationOptionInstallationFailed": "Installationsfähler",
"NotificationOptionNewLibraryContent": "Nöie Inhaut hinzuegfüegt",
"NotificationOptionPluginError": "Plugin-Fäuer",
"NotificationOptionPluginInstalled": "Plugin installiert",
@@ -120,5 +120,9 @@
"Forced": "Erzwungen",
"Default": "Standard",
"TaskOptimizeDatabase": "Datenbank optimieren",
- "External": "Extern"
+ "External": "Extern",
+ "TaskOptimizeDatabaseDescription": "Kompromiert d Datenbank und trennt freie Speicherplatz. Durch die Ufagb cha d Leistig nach em ne Scan vor Bibliothek oder andere Ufgabe verbesseret werde.",
+ "HearingImpaired": "Hörgschädigti",
+ "TaskKeyframeExtractor": "Keyframe-Extraktor",
+ "TaskKeyframeExtractorDescription": "Extrahiert Keyframes us Videodateien zum erstelle vo genauere HLS Playliste. Die Ufgab cha für e langi Zyt laufe."
}
diff --git a/Emby.Server.Implementations/Plugins/PluginManager.cs b/Emby.Server.Implementations/Plugins/PluginManager.cs
index f2212f4dcb..7c23254a12 100644
--- a/Emby.Server.Implementations/Plugins/PluginManager.cs
+++ b/Emby.Server.Implementations/Plugins/PluginManager.cs
@@ -123,41 +123,64 @@ namespace Emby.Server.Implementations.Plugins
continue;
}
+ var assemblyLoadContext = new PluginLoadContext(plugin.Path);
+ _assemblyLoadContexts.Add(assemblyLoadContext);
+
+ var assemblies = new List<Assembly>(plugin.DllFiles.Count);
+ var loadedAll = true;
+
foreach (var file in plugin.DllFiles)
{
- Assembly assembly;
try
{
- var assemblyLoadContext = new PluginLoadContext(file);
- _assemblyLoadContexts.Add(assemblyLoadContext);
-
- assembly = assemblyLoadContext.LoadFromAssemblyPath(file);
-
- // Load all required types to verify that the plugin will load
- assembly.GetTypes();
+ assemblies.Add(assemblyLoadContext.LoadFromAssemblyPath(file));
}
catch (FileLoadException ex)
{
- _logger.LogError(ex, "Failed to load assembly {Path}. Disabling plugin.", file);
+ _logger.LogError(ex, "Failed to load assembly {Path}. Disabling plugin", file);
ChangePluginState(plugin, PluginStatus.Malfunctioned);
- continue;
+ loadedAll = false;
+ break;
+ }
+#pragma warning disable CA1031 // Do not catch general exception types
+ catch (Exception ex)
+#pragma warning restore CA1031 // Do not catch general exception types
+ {
+ _logger.LogError(ex, "Failed to load assembly {Path}. Unknown exception was thrown. Disabling plugin", file);
+ ChangePluginState(plugin, PluginStatus.Malfunctioned);
+ loadedAll = false;
+ break;
+ }
+ }
+
+ if (!loadedAll)
+ {
+ continue;
+ }
+
+ foreach (var assembly in assemblies)
+ {
+ try
+ {
+ // Load all required types to verify that the plugin will load
+ assembly.GetTypes();
}
catch (SystemException ex) when (ex is TypeLoadException or ReflectionTypeLoadException) // Undocumented exception
{
- _logger.LogError(ex, "Failed to load assembly {Path}. This error occurs when a plugin references an incompatible version of one of the shared libraries. Disabling plugin.", file);
+ _logger.LogError(ex, "Failed to load assembly {Path}. This error occurs when a plugin references an incompatible version of one of the shared libraries. Disabling plugin", assembly.Location);
ChangePluginState(plugin, PluginStatus.NotSupported);
- continue;
+ break;
}
#pragma warning disable CA1031 // Do not catch general exception types
catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
{
- _logger.LogError(ex, "Failed to load assembly {Path}. Unknown exception was thrown. Disabling plugin.", file);
+ _logger.LogError(ex, "Failed to load assembly {Path}. Unknown exception was thrown. Disabling plugin", assembly.Location);
ChangePluginState(plugin, PluginStatus.Malfunctioned);
- continue;
+ break;
}
- _logger.LogInformation("Loaded assembly {Assembly} from {Path}", assembly.FullName, file);
+ _logger.LogInformation("Loaded assembly {Assembly} from {Path}", assembly.FullName, assembly.Location);
yield return assembly;
}
}