aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations
diff options
context:
space:
mode:
Diffstat (limited to 'Emby.Server.Implementations')
-rw-r--r--Emby.Server.Implementations/Dto/DtoService.cs20
-rw-r--r--Emby.Server.Implementations/IO/ManagedFileSystem.cs37
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs2
-rw-r--r--Emby.Server.Implementations/Localization/Core/ca.json19
-rw-r--r--Emby.Server.Implementations/Localization/Core/de.json28
-rw-r--r--Emby.Server.Implementations/Localization/Core/nb.json3
-rw-r--r--Emby.Server.Implementations/Localization/Core/tr.json5
-rw-r--r--Emby.Server.Implementations/Localization/Core/zh-TW.json2
-rw-r--r--Emby.Server.Implementations/Localization/iso6392.txt2
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs7
-rw-r--r--Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs2
-rw-r--r--Emby.Server.Implementations/TV/TVSeriesManager.cs23
12 files changed, 95 insertions, 55 deletions
diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs
index d5e1f5124..8a901516c 100644
--- a/Emby.Server.Implementations/Dto/DtoService.cs
+++ b/Emby.Server.Implementations/Dto/DtoService.cs
@@ -582,16 +582,22 @@ namespace Emby.Server.Implementations.Dto
{
baseItemPerson.PrimaryImageTag = GetTagAndFillBlurhash(dto, entity, ImageType.Primary);
baseItemPerson.Id = entity.Id.ToString("N", CultureInfo.InvariantCulture);
- // Only add BlurHash for the person's image.
- baseItemPerson.ImageBlurHashes = new Dictionary<ImageType, Dictionary<string, string>>();
- foreach (var (imageType, blurHash) in dto.ImageBlurHashes)
+ if (dto.ImageBlurHashes != null)
{
- baseItemPerson.ImageBlurHashes[imageType] = new Dictionary<string, string>();
- foreach (var (imageId, blurHashValue) in blurHash)
+ // Only add BlurHash for the person's image.
+ baseItemPerson.ImageBlurHashes = new Dictionary<ImageType, Dictionary<string, string>>();
+ foreach (var (imageType, blurHash) in dto.ImageBlurHashes)
{
- if (string.Equals(baseItemPerson.PrimaryImageTag, imageId, StringComparison.OrdinalIgnoreCase))
+ if (blurHash != null)
{
- baseItemPerson.ImageBlurHashes[imageType][imageId] = blurHashValue;
+ baseItemPerson.ImageBlurHashes[imageType] = new Dictionary<string, string>();
+ foreach (var (imageId, blurHashValue) in blurHash)
+ {
+ if (string.Equals(baseItemPerson.PrimaryImageTag, imageId, StringComparison.OrdinalIgnoreCase))
+ {
+ baseItemPerson.ImageBlurHashes[imageType][imageId] = blurHashValue;
+ }
+ }
}
}
}
diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs
index 3cb025111..5ebc9b61b 100644
--- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs
+++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs
@@ -582,9 +582,7 @@ namespace Emby.Server.Implementations.IO
public virtual IEnumerable<FileSystemMetadata> GetDirectories(string path, bool recursive = false)
{
- var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
-
- return ToMetadata(new DirectoryInfo(path).EnumerateDirectories("*", searchOption));
+ return ToMetadata(new DirectoryInfo(path).EnumerateDirectories("*", GetEnumerationOptions(recursive)));
}
public virtual IEnumerable<FileSystemMetadata> GetFiles(string path, bool recursive = false)
@@ -594,16 +592,16 @@ namespace Emby.Server.Implementations.IO
public virtual IEnumerable<FileSystemMetadata> GetFiles(string path, IReadOnlyList<string> extensions, bool enableCaseSensitiveExtensions, bool recursive = false)
{
- var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
+ var enumerationOptions = GetEnumerationOptions(recursive);
// On linux and osx the search pattern is case sensitive
// If we're OK with case-sensitivity, and we're only filtering for one extension, then use the native method
if ((enableCaseSensitiveExtensions || _isEnvironmentCaseInsensitive) && extensions != null && extensions.Count == 1)
{
- return ToMetadata(new DirectoryInfo(path).EnumerateFiles("*" + extensions[0], searchOption));
+ return ToMetadata(new DirectoryInfo(path).EnumerateFiles("*" + extensions[0], enumerationOptions));
}
- var files = new DirectoryInfo(path).EnumerateFiles("*", searchOption);
+ var files = new DirectoryInfo(path).EnumerateFiles("*", enumerationOptions);
if (extensions != null && extensions.Count > 0)
{
@@ -625,10 +623,10 @@ namespace Emby.Server.Implementations.IO
public virtual IEnumerable<FileSystemMetadata> GetFileSystemEntries(string path, bool recursive = false)
{
var directoryInfo = new DirectoryInfo(path);
- var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
+ var enumerationOptions = GetEnumerationOptions(recursive);
- return ToMetadata(directoryInfo.EnumerateDirectories("*", searchOption))
- .Concat(ToMetadata(directoryInfo.EnumerateFiles("*", searchOption)));
+ return ToMetadata(directoryInfo.EnumerateDirectories("*", enumerationOptions))
+ .Concat(ToMetadata(directoryInfo.EnumerateFiles("*", enumerationOptions)));
}
private IEnumerable<FileSystemMetadata> ToMetadata(IEnumerable<FileSystemInfo> infos)
@@ -638,8 +636,7 @@ namespace Emby.Server.Implementations.IO
public virtual IEnumerable<string> GetDirectoryPaths(string path, bool recursive = false)
{
- var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
- return Directory.EnumerateDirectories(path, "*", searchOption);
+ return Directory.EnumerateDirectories(path, "*", GetEnumerationOptions(recursive));
}
public virtual IEnumerable<string> GetFilePaths(string path, bool recursive = false)
@@ -649,16 +646,16 @@ namespace Emby.Server.Implementations.IO
public virtual IEnumerable<string> GetFilePaths(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive = false)
{
- var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
+ var enumerationOptions = GetEnumerationOptions(recursive);
// On linux and osx the search pattern is case sensitive
// If we're OK with case-sensitivity, and we're only filtering for one extension, then use the native method
if ((enableCaseSensitiveExtensions || _isEnvironmentCaseInsensitive) && extensions != null && extensions.Length == 1)
{
- return Directory.EnumerateFiles(path, "*" + extensions[0], searchOption);
+ return Directory.EnumerateFiles(path, "*" + extensions[0], enumerationOptions);
}
- var files = Directory.EnumerateFiles(path, "*", searchOption);
+ var files = Directory.EnumerateFiles(path, "*", enumerationOptions);
if (extensions != null && extensions.Length > 0)
{
@@ -679,8 +676,16 @@ namespace Emby.Server.Implementations.IO
public virtual IEnumerable<string> GetFileSystemEntryPaths(string path, bool recursive = false)
{
- var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
- return Directory.EnumerateFileSystemEntries(path, "*", searchOption);
+ return Directory.EnumerateFileSystemEntries(path, "*", GetEnumerationOptions(recursive));
+ }
+
+ private EnumerationOptions GetEnumerationOptions(bool recursive)
+ {
+ return new EnumerationOptions
+ {
+ RecurseSubdirectories = recursive,
+ IgnoreInaccessible = true
+ };
}
private static void RunProcess(string path, string args, string workingDirectory)
diff --git a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs
index 41561916f..c76d41e5c 100644
--- a/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs
+++ b/Emby.Server.Implementations/Library/Resolvers/PlaylistResolver.cs
@@ -41,7 +41,7 @@ namespace Emby.Server.Implementations.Library.Resolvers
}
// It's a directory-based playlist if the directory contains a playlist file
- var filePaths = Directory.EnumerateFiles(args.Path);
+ var filePaths = Directory.EnumerateFiles(args.Path, "*", new EnumerationOptions { IgnoreInaccessible = true });
if (filePaths.Any(f => f.EndsWith(PlaylistXmlSaver.DefaultPlaylistFilename, StringComparison.OrdinalIgnoreCase)))
{
return new Playlist
diff --git a/Emby.Server.Implementations/Localization/Core/ca.json b/Emby.Server.Implementations/Localization/Core/ca.json
index b7852eccb..fd8437b6d 100644
--- a/Emby.Server.Implementations/Localization/Core/ca.json
+++ b/Emby.Server.Implementations/Localization/Core/ca.json
@@ -18,10 +18,10 @@
"HeaderAlbumArtists": "Artistes del Àlbum",
"HeaderContinueWatching": "Continua Veient",
"HeaderFavoriteAlbums": "Àlbums Preferits",
- "HeaderFavoriteArtists": "Artistes Preferits",
- "HeaderFavoriteEpisodes": "Episodis Preferits",
- "HeaderFavoriteShows": "Programes Preferits",
- "HeaderFavoriteSongs": "Cançons Preferides",
+ "HeaderFavoriteArtists": "Artistes Predilectes",
+ "HeaderFavoriteEpisodes": "Episodis Predilectes",
+ "HeaderFavoriteShows": "Programes Predilectes",
+ "HeaderFavoriteSongs": "Cançons Predilectes",
"HeaderLiveTV": "TV en Directe",
"HeaderNextUp": "A continuació",
"HeaderRecordingGroups": "Grups d'Enregistrament",
@@ -36,7 +36,7 @@
"MessageApplicationUpdatedTo": "El Servidor de Jellyfin ha estat actualitzat a {0}",
"MessageNamedServerConfigurationUpdatedWithValue": "La secció {0} de la configuració del servidor ha estat actualitzada",
"MessageServerConfigurationUpdated": "S'ha actualitzat la configuració del servidor",
- "MixedContent": "Contingut mesclat",
+ "MixedContent": "Contingut barrejat",
"Movies": "Pel·lícules",
"Music": "Música",
"MusicVideos": "Vídeos musicals",
@@ -76,7 +76,7 @@
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
"SubtitleDownloadFailureFromForItem": "Els subtítols no s'han pogut baixar de {0} per {1}",
"Sync": "Sincronitzar",
- "System": "System",
+ "System": "Sistema",
"TvShows": "Espectacles de TV",
"User": "User",
"UserCreatedWithName": "S'ha creat l'usuari {0}",
@@ -113,5 +113,10 @@
"TasksChannelsCategory": "Canals d'internet",
"TasksApplicationCategory": "Aplicació",
"TasksLibraryCategory": "Biblioteca",
- "TasksMaintenanceCategory": "Manteniment"
+ "TasksMaintenanceCategory": "Manteniment",
+ "TaskCleanActivityLogDescription": "Eliminat entrades del registre d'activitats mes antigues que l'antiguitat configurada.",
+ "TaskCleanActivityLog": "Buidar Registre d'Activitat",
+ "Undefined": "Indefinit",
+ "Forced": "Forçat",
+ "Default": "Defecto"
}
diff --git a/Emby.Server.Implementations/Localization/Core/de.json b/Emby.Server.Implementations/Localization/Core/de.json
index 6ab22b8a4..4a505d0b3 100644
--- a/Emby.Server.Implementations/Localization/Core/de.json
+++ b/Emby.Server.Implementations/Localization/Core/de.json
@@ -94,22 +94,22 @@
"VersionNumber": "Version {0}",
"TaskDownloadMissingSubtitlesDescription": "Durchsucht das Internet nach fehlenden Untertiteln, basierend auf den Meta Einstellungen.",
"TaskDownloadMissingSubtitles": "Lade fehlende Untertitel herunter",
- "TaskRefreshChannelsDescription": "Erneuere Internet Kanal Informationen.",
- "TaskRefreshChannels": "Erneuere Kanäle",
- "TaskCleanTranscodeDescription": "Löscht Transkodierdateien welche älter als ein Tag sind.",
- "TaskCleanTranscode": "Lösche Transkodier Pfad",
- "TaskUpdatePluginsDescription": "Lädt Updates für Plugins herunter, welche dazu eingestellt sind automatisch zu updaten und installiert sie.",
- "TaskUpdatePlugins": "Update Plugins",
- "TaskRefreshPeopleDescription": "Erneuert Metadaten für Schauspieler und Regisseure in deinen Bibliotheken.",
- "TaskRefreshPeople": "Erneuere Schauspieler",
- "TaskCleanLogsDescription": "Lösche Log Dateien die älter als {0} Tage sind.",
- "TaskCleanLogs": "Lösche Log Pfad",
- "TaskRefreshLibraryDescription": "Scanne alle Bibliotheken für hinzugefügte Datein und erneuere Metadaten.",
+ "TaskRefreshChannelsDescription": "Aktualisiere Internet Kanal Informationen.",
+ "TaskRefreshChannels": "Aktualisiere Kanäle",
+ "TaskCleanTranscodeDescription": "Löscht Transkodierdateien, welche älter als einen Tag sind.",
+ "TaskCleanTranscode": "Lösche Transkodier-Pfad",
+ "TaskUpdatePluginsDescription": "Lädt Updates für Plugins herunter, welche für automatische Updates konfiguriert sind und installiert diese.",
+ "TaskUpdatePlugins": "Aktualisiere Plugins",
+ "TaskRefreshPeopleDescription": "Aktualisiert Metadaten für Schauspieler und Regisseure in deinen Bibliotheken.",
+ "TaskRefreshPeople": "Aktualisiere Schauspieler",
+ "TaskCleanLogsDescription": "Lösche Log Dateien, die älter als {0} Tage sind.",
+ "TaskCleanLogs": "Lösche Log-Verzeichnis",
+ "TaskRefreshLibraryDescription": "Scanne alle Bibliotheken nach neu hinzugefügten Dateien und aktualisiere Metadaten.",
"TaskRefreshLibrary": "Scanne Medien-Bibliothek",
- "TaskRefreshChapterImagesDescription": "Kreiert Vorschaubilder für Videos welche Kapitel haben.",
+ "TaskRefreshChapterImagesDescription": "Erstellt Vorschaubilder für Videos, welche Kapitel besitzen.",
"TaskRefreshChapterImages": "Extrahiert Kapitel-Bilder",
- "TaskCleanCacheDescription": "Löscht Zwischenspeicherdatein die nicht länger von System gebraucht werden.",
- "TaskCleanCache": "Leere Cache Pfad",
+ "TaskCleanCacheDescription": "Löscht nicht mehr benötigte Zwischenspeicherdateien.",
+ "TaskCleanCache": "Leere Zwischenspeicher",
"TasksChannelsCategory": "Internet Kanäle",
"TasksApplicationCategory": "Anwendung",
"TasksLibraryCategory": "Bibliothek",
diff --git a/Emby.Server.Implementations/Localization/Core/nb.json b/Emby.Server.Implementations/Localization/Core/nb.json
index 3b016fe62..d5bca9f6c 100644
--- a/Emby.Server.Implementations/Localization/Core/nb.json
+++ b/Emby.Server.Implementations/Localization/Core/nb.json
@@ -117,5 +117,6 @@
"TaskCleanActivityLog": "Tøm aktivitetslogg",
"Undefined": "Udefinert",
"Forced": "Tvungen",
- "Default": "Standard"
+ "Default": "Standard",
+ "TaskCleanActivityLogDescription": "Sletter oppføringer i aktivitetsloggen som er eldre enn den konfigurerte alderen."
}
diff --git a/Emby.Server.Implementations/Localization/Core/tr.json b/Emby.Server.Implementations/Localization/Core/tr.json
index 885663eed..c6b904045 100644
--- a/Emby.Server.Implementations/Localization/Core/tr.json
+++ b/Emby.Server.Implementations/Localization/Core/tr.json
@@ -12,7 +12,7 @@
"DeviceOfflineWithName": "{0} bağlantısı kesildi",
"DeviceOnlineWithName": "{0} bağlı",
"FailedLoginAttemptWithUserName": "{0} adresinden giriş başarısız oldu",
- "Favorites": "Favorilerim",
+ "Favorites": "Favoriler",
"Folders": "Klasörler",
"Genres": "Türler",
"HeaderAlbumArtists": "Albüm Sanatçıları",
@@ -117,5 +117,6 @@
"TaskCleanActivityLog": "İşlem Günlüğünü Temizle",
"TaskCleanActivityLogDescription": "Belirtilen sureden daha eski etkinlik log kayıtları silindi.",
"Undefined": "Bilinmeyen",
- "Default": "Varsayılan"
+ "Default": "Varsayılan",
+ "Forced": "Zorla"
}
diff --git a/Emby.Server.Implementations/Localization/Core/zh-TW.json b/Emby.Server.Implementations/Localization/Core/zh-TW.json
index 6494c0b54..affb0e099 100644
--- a/Emby.Server.Implementations/Localization/Core/zh-TW.json
+++ b/Emby.Server.Implementations/Localization/Core/zh-TW.json
@@ -1,6 +1,6 @@
{
"Albums": "專輯",
- "AppDeviceValues": "軟體:{0},裝置:{1}",
+ "AppDeviceValues": "App:{0},裝置:{1}",
"Application": "應用程式",
"Artists": "演出者",
"AuthenticationSucceededWithUserName": "{0} 成功授權",
diff --git a/Emby.Server.Implementations/Localization/iso6392.txt b/Emby.Server.Implementations/Localization/iso6392.txt
index 40f8614f1..488901822 100644
--- a/Emby.Server.Implementations/Localization/iso6392.txt
+++ b/Emby.Server.Implementations/Localization/iso6392.txt
@@ -77,6 +77,8 @@ chb|||Chibcha|chibcha
che||ce|Chechen|tchétchène
chg|||Chagatai|djaghataï
chi|zho|zh|Chinese|chinois
+chi|zho|zh-tw|Chinese; Traditional|chinois
+chi|zho|zh-hk|Chinese; Hong Kong|chinois
chk|||Chuukese|chuuk
chm|||Mari|mari
chn|||Chinook jargon|chinook, jargon
diff --git a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
index 29440b64a..d3cf3bf3f 100644
--- a/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs
@@ -177,7 +177,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
lock (_lastExecutionResultSyncLock)
{
- using FileStream createStream = File.OpenWrite(path);
+ using FileStream createStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
JsonSerializer.SerializeAsync(createStream, value, _jsonOptions);
}
}
@@ -577,9 +577,8 @@ namespace Emby.Server.Implementations.ScheduledTasks
var path = GetConfigurationFilePath();
Directory.CreateDirectory(Path.GetDirectoryName(path));
-
- var json = JsonSerializer.Serialize(triggers, _jsonOptions);
- File.WriteAllText(path, json, Encoding.UTF8);
+ using FileStream createStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None);
+ JsonSerializer.SerializeAsync(createStream, triggers, _jsonOptions);
}
/// <summary>
diff --git a/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs b/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs
index 8b67d37d7..3b40320ab 100644
--- a/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs
+++ b/Emby.Server.Implementations/ScheduledTasks/Triggers/DailyTrigger.cs
@@ -50,7 +50,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
var dueTime = triggerDate - now;
- logger.LogInformation("Daily trigger for {Task} set to fire at {TriggerDate:g}, which is {DueTime:g} from now.", taskName, triggerDate, dueTime);
+ logger.LogInformation("Daily trigger for {Task} set to fire at {TriggerDate:yyyy-MM-dd HH:mm:ss.fff zzz}, which is {DueTime:c} from now.", taskName, triggerDate, dueTime);
Timer = new Timer(state => OnTriggered(), null, dueTime, TimeSpan.FromMilliseconds(-1));
}
diff --git a/Emby.Server.Implementations/TV/TVSeriesManager.cs b/Emby.Server.Implementations/TV/TVSeriesManager.cs
index f0734340b..839b62448 100644
--- a/Emby.Server.Implementations/TV/TVSeriesManager.cs
+++ b/Emby.Server.Implementations/TV/TVSeriesManager.cs
@@ -143,10 +143,31 @@ namespace Emby.Server.Implementations.TV
var allNextUp = seriesKeys
.Select(i => GetNextUp(i, currentUser, dtoOptions));
+ // If viewing all next up for all series, remove first episodes
+ // But if that returns empty, keep those first episodes (avoid completely empty view)
+ var alwaysEnableFirstEpisode = !string.IsNullOrEmpty(request.SeriesId);
+ var anyFound = false;
+
return allNextUp
.Where(i =>
{
- return i.Item1 != DateTime.MinValue;
+ if (request.DisableFirstEpisode)
+ {
+ return i.Item1 != DateTime.MinValue;
+ }
+
+ if (alwaysEnableFirstEpisode || i.Item1 != DateTime.MinValue)
+ {
+ anyFound = true;
+ return true;
+ }
+
+ if (!anyFound && i.Item1 == DateTime.MinValue)
+ {
+ return true;
+ }
+
+ return false;
})
.Select(i => i.Item2())
.Where(i => i != null);