diff options
| author | Bond-009 <bond.009@outlook.com> | 2026-05-15 15:44:22 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-05-15 15:44:22 +0200 |
| commit | 9d420271ad4d9468683fda79d906bcd348f4979c (patch) | |
| tree | d6adbc5e2bc327242c50c81e200167720cdbd3d2 /Jellyfin.Api/Controllers | |
| parent | d93e2d6667872ea16c523202f200c873fc8191ad (diff) | |
| parent | fae4950ac2b5918081198ee5f876dd82ca81ae5d (diff) | |
Merge pull request #9787 from TheMelmacian/feature/language_filters
New filters for audio and subtitle languages
Diffstat (limited to 'Jellyfin.Api/Controllers')
| -rw-r--r-- | Jellyfin.Api/Controllers/FilterController.cs | 37 | ||||
| -rw-r--r-- | Jellyfin.Api/Controllers/ItemsController.cs | 35 | ||||
| -rw-r--r-- | Jellyfin.Api/Controllers/TrailersController.cs | 6 |
3 files changed, 77 insertions, 1 deletions
diff --git a/Jellyfin.Api/Controllers/FilterController.cs b/Jellyfin.Api/Controllers/FilterController.cs index 2f53784db1..cfc8be28ae 100644 --- a/Jellyfin.Api/Controllers/FilterController.cs +++ b/Jellyfin.Api/Controllers/FilterController.cs @@ -8,6 +8,8 @@ using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Globalization; using MediaBrowser.Model.Querying; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -24,16 +26,19 @@ public class FilterController : BaseJellyfinApiController { private readonly ILibraryManager _libraryManager; private readonly IUserManager _userManager; + private readonly ILocalizationManager _localization; /// <summary> /// Initializes a new instance of the <see cref="FilterController"/> class. /// </summary> /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param> /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param> - public FilterController(ILibraryManager libraryManager, IUserManager userManager) + /// <param name="localization">Instance of the <see cref="ILocalizationManager"/> interface.</param> + public FilterController(ILibraryManager libraryManager, IUserManager userManager, ILocalizationManager localization) { _libraryManager = libraryManager; _userManager = userManager; + _localization = localization; } /// <summary> @@ -183,6 +188,36 @@ public class FilterController : BaseJellyfinApiController }).ToArray(); } + if (includeItemTypes.Contains(BaseItemKind.Movie) || includeItemTypes.Contains(BaseItemKind.Series)) + { + filters.AudioLanguages = _libraryManager + .GetMediaStreamLanguages(MediaStreamType.Audio) + .Select(language => + { + var culture = _localization.FindLanguageInfo(language); + return new NameValuePair + { + Name = culture is null ? language : $"{culture.DisplayName} ({language})", + Value = language + }; + }) + .OrderBy(l => l.Name) + .ToArray(); + filters.SubtitleLanguages = _libraryManager + .GetMediaStreamLanguages(MediaStreamType.Subtitle) + .Select(language => + { + var culture = _localization.FindLanguageInfo(language); + return new NameValuePair + { + Name = culture is null ? language : $"{culture.DisplayName} ({language})", + Value = language + }; + }) + .OrderBy(l => l.Name) + .ToArray(); + } + return filters; } } diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs index e6ba4e7f29..43e4737694 100644 --- a/Jellyfin.Api/Controllers/ItemsController.cs +++ b/Jellyfin.Api/Controllers/ItemsController.cs @@ -157,6 +157,8 @@ public class ItemsController : BaseJellyfinApiController /// <param name="nameLessThan">Optional filter by items whose name is equally or lesser than a given input string.</param> /// <param name="studioIds">Optional. If specified, results will be filtered based on studio id. This allows multiple, pipe delimited.</param> /// <param name="genreIds">Optional. If specified, results will be filtered based on genre id. This allows multiple, pipe delimited.</param> + /// <param name="audioLanguages">Optional. If specified, results will be filtered based on audio language. This allows multiple, comma delimited values.</param> + /// <param name="subtitleLanguages">Optional. If specified, results will be filtered based on subtitle language. This allows multiple, comma delimited values.</param> /// <param name="enableTotalRecordCount">Optional. Enable the total record count.</param> /// <param name="enableImages">Optional, include image information in output.</param> /// <returns>A <see cref="QueryResult{BaseItemDto}"/> with the items.</returns> @@ -247,6 +249,8 @@ public class ItemsController : BaseJellyfinApiController [FromQuery] string? nameLessThan, [FromQuery, ModelBinder(typeof(CommaDelimitedCollectionModelBinder))] Guid[] studioIds, [FromQuery, ModelBinder(typeof(CommaDelimitedCollectionModelBinder))] Guid[] genreIds, + [FromQuery, ModelBinder(typeof(CommaDelimitedCollectionModelBinder))] string[] audioLanguages, + [FromQuery, ModelBinder(typeof(CommaDelimitedCollectionModelBinder))] string[] subtitleLanguages, [FromQuery] bool enableTotalRecordCount = true, [FromQuery] bool? enableImages = true) { @@ -399,6 +403,8 @@ public class ItemsController : BaseJellyfinApiController MinDateLastSavedForUser = minDateLastSavedForUser?.ToUniversalTime(), MinPremiereDate = minPremiereDate?.ToUniversalTime(), MaxPremiereDate = maxPremiereDate?.ToUniversalTime(), + AudioLanguages = audioLanguages, + SubtitleLanguages = subtitleLanguages, }; if (ids.Length != 0 || !string.IsNullOrWhiteSpace(searchTerm)) @@ -406,6 +412,33 @@ public class ItemsController : BaseJellyfinApiController query.CollapseBoxSetItems = false; } + if (query.SubtitleLanguages.Count > 0 && query.HasSubtitles.HasValue) + { + if (query.HasSubtitles.Value) + { + // if we check for specific subtitles we don't need a separate check for subtitle existence + query.HasSubtitles = null; + } + else + { + // if we search for items without subtitles, we don't need to check for subtitles of a specific language + query.SubtitleLanguages = []; + } + } + + // for filter values that rely on media streams, we need to include alternative and linked versions + if (query.HasSubtitles.HasValue + || query.SubtitleLanguages.Count > 0 + || query.AudioLanguages.Count > 0 + || query.Is3D.HasValue + || query.IsHD.HasValue + || query.Is4K.HasValue + || query.VideoTypes.Length > 0 + ) + { + query.IncludeOwnedItems = true; + } + query.ApplyFilters(filters); // Filter by Series Status @@ -785,6 +818,8 @@ public class ItemsController : BaseJellyfinApiController nameLessThan, studioIds, genreIds, + [], + [], enableTotalRecordCount, enableImages).ConfigureAwait(false); diff --git a/Jellyfin.Api/Controllers/TrailersController.cs b/Jellyfin.Api/Controllers/TrailersController.cs index e2075c2b8d..121db66858 100644 --- a/Jellyfin.Api/Controllers/TrailersController.cs +++ b/Jellyfin.Api/Controllers/TrailersController.cs @@ -115,6 +115,8 @@ public class TrailersController : BaseJellyfinApiController /// <param name="nameLessThan">Optional filter by items whose name is equally or lesser than a given input string.</param> /// <param name="studioIds">Optional. If specified, results will be filtered based on studio id. This allows multiple, pipe delimited.</param> /// <param name="genreIds">Optional. If specified, results will be filtered based on genre id. This allows multiple, pipe delimited.</param> + /// <param name="audioLanguages">Optional. If specified, results will be filtered based on audio language. This allows multiple, comma delimited values.</param> + /// <param name="subtitleLanguages">Optional. If specified, results will be filtered based on subtitale language. This allows multiple, comma delimited values.</param> /// <param name="enableTotalRecordCount">Optional. Enable the total record count.</param> /// <param name="enableImages">Optional, include image information in output.</param> /// <returns>A <see cref="QueryResult{BaseItemDto}"/> with the trailers.</returns> @@ -203,6 +205,8 @@ public class TrailersController : BaseJellyfinApiController [FromQuery] string? nameLessThan, [FromQuery, ModelBinder(typeof(CommaDelimitedCollectionModelBinder))] Guid[] studioIds, [FromQuery, ModelBinder(typeof(CommaDelimitedCollectionModelBinder))] Guid[] genreIds, + [FromQuery, ModelBinder(typeof(CommaDelimitedCollectionModelBinder))] string[] audioLanguages, + [FromQuery, ModelBinder(typeof(CommaDelimitedCollectionModelBinder))] string[] subtitleLanguages, [FromQuery] bool enableTotalRecordCount = true, [FromQuery] bool? enableImages = true) { @@ -294,6 +298,8 @@ public class TrailersController : BaseJellyfinApiController nameLessThan, studioIds, genreIds, + audioLanguages, + subtitleLanguages, enableTotalRecordCount, enableImages).ConfigureAwait(false); } |
