diff --git a/CHANGELOG.md b/CHANGELOG.md index 78e00dca..c369f1a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - This allows a single Plex server to connect to multiple ETV instances - Include *all* language codes from media library in preferred audio and subtitle language options - Language codes where an English name cannot be found will be at the bottom of the list +- Fix local libraries to detect external subtitle files with unrecognized language codes +- Fix playback selection of subtitles with unrecognized language codes ### Changed - Remove some unnecessary API calls related to media server scanning and paging diff --git a/ErsatzTV.Application/Channels/Commands/CreateChannelHandler.cs b/ErsatzTV.Application/Channels/Commands/CreateChannelHandler.cs index 49498308..a59545d1 100644 --- a/ErsatzTV.Application/Channels/Commands/CreateChannelHandler.cs +++ b/ErsatzTV.Application/Channels/Commands/CreateChannelHandler.cs @@ -1,5 +1,4 @@ -using System.Globalization; -using System.Text.RegularExpressions; +using System.Text.RegularExpressions; using System.Threading.Channels; using ErsatzTV.Core; using ErsatzTV.Core.Domain; @@ -39,7 +38,6 @@ public class CreateChannelHandler( private static async Task> Validate(TvContext dbContext, CreateChannel request) => (ValidateName(request), await ValidateNumber(dbContext, request), await FFmpegProfileMustExist(dbContext, request), - ValidatePreferredSubtitleLanguage(request), await WatermarkMustExist(dbContext, request), await FillerPresetMustExist(dbContext, request)) .Apply( @@ -47,7 +45,6 @@ public class CreateChannelHandler( name, number, ffmpegProfileId, - preferredSubtitleLanguageCode, watermarkId, fillerPresetId) => { @@ -76,7 +73,7 @@ public class CreateChannelHandler( Artwork = artwork, PreferredAudioLanguageCode = request.PreferredAudioLanguageCode, PreferredAudioTitle = request.PreferredAudioTitle, - PreferredSubtitleLanguageCode = preferredSubtitleLanguageCode, + PreferredSubtitleLanguageCode = request.PreferredSubtitleLanguageCode, SubtitleMode = request.SubtitleMode, MusicVideoCreditsMode = request.MusicVideoCreditsMode, MusicVideoCreditsTemplate = request.MusicVideoCreditsTemplate @@ -99,13 +96,6 @@ public class CreateChannelHandler( createChannel.NotEmpty(c => c.Name) .Bind(_ => createChannel.NotLongerThan(50)(c => c.Name)); - private static Validation ValidatePreferredSubtitleLanguage(CreateChannel createChannel) => - Optional(createChannel.PreferredSubtitleLanguageCode ?? string.Empty) - .Filter( - lc => string.IsNullOrWhiteSpace(lc) || CultureInfo.GetCultures(CultureTypes.NeutralCultures).Any( - ci => string.Equals(ci.ThreeLetterISOLanguageName, lc, StringComparison.OrdinalIgnoreCase))) - .ToValidation("Preferred subtitle language code is invalid"); - private static async Task> ValidateNumber( TvContext dbContext, CreateChannel createChannel) diff --git a/ErsatzTV.Infrastructure/Data/Repositories/MediaItemRepository.cs b/ErsatzTV.Infrastructure/Data/Repositories/MediaItemRepository.cs index 6bdb5772..21409bfa 100644 --- a/ErsatzTV.Infrastructure/Data/Repositories/MediaItemRepository.cs +++ b/ErsatzTV.Infrastructure/Data/Repositories/MediaItemRepository.cs @@ -217,6 +217,8 @@ public class MediaItemRepository : IMediaItemRepository @"SELECT LanguageCode FROM (SELECT Language AS LanguageCode FROM MediaStream WHERE Language IS NOT NULL + UNION ALL SELECT Language AS LanguageCode + FROM Subtitle WHERE Language IS NOT NULL UNION ALL SELECT PreferredAudioLanguageCode AS LanguageCode FROM Channel WHERE PreferredAudioLanguageCode IS NOT NULL) AS A GROUP BY LanguageCode diff --git a/ErsatzTV.Infrastructure/Extensions/LanguageCodeQueryableExtensions.cs b/ErsatzTV.Infrastructure/Extensions/LanguageCodeQueryableExtensions.cs index a26a7648..a9c66d63 100644 --- a/ErsatzTV.Infrastructure/Extensions/LanguageCodeQueryableExtensions.cs +++ b/ErsatzTV.Infrastructure/Extensions/LanguageCodeQueryableExtensions.cs @@ -55,7 +55,7 @@ public static class LanguageCodeQueryableExtensions .Filter(lc => validCodes.Contains(lc.ThreeCode1) || validCodes.Contains(lc.ThreeCode2)) .ToListAsync(); - var result = new System.Collections.Generic.HashSet(); + var result = new System.Collections.Generic.HashSet(validCodes); foreach (LanguageCode language in maybeLanguages) { if (!string.IsNullOrWhiteSpace(language.ThreeCode1)) diff --git a/ErsatzTV.Scanner/Core/Metadata/LocalSubtitlesProvider.cs b/ErsatzTV.Scanner/Core/Metadata/LocalSubtitlesProvider.cs index 120dc660..a3f59347 100644 --- a/ErsatzTV.Scanner/Core/Metadata/LocalSubtitlesProvider.cs +++ b/ErsatzTV.Scanner/Core/Metadata/LocalSubtitlesProvider.cs @@ -156,6 +156,29 @@ public class LocalSubtitlesProvider : ILocalSubtitlesProvider Option maybeCulture = languageCodes.Find( ci => ci.TwoLetterISOLanguageName == language || ci.ThreeLetterISOLanguageName == language); + if (maybeCulture.IsNone) + { + _logger.LogDebug( + "Located {Attribute} with unknown language code {Code} at {Path}", + "External Subtitles", + language, + file); + + result.Add( + new Subtitle + { + SubtitleKind = SubtitleKind.Sidecar, + Codec = codec, + Default = false, + Forced = forced, + SDH = sdh, + Language = language, + Path = saveFullPath ? file : Path.GetFileName(file), + DateAdded = DateTime.UtcNow, + DateUpdated = _localFileSystem.GetLastWriteTime(file) + }); + } + foreach (CultureInfo culture in maybeCulture) { _logger.LogDebug("Located {Attribute} at {Path}", "External Subtitles", file);