aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheMelmacian <76712303+TheMelmacian@users.noreply.github.com>2026-05-25 23:40:40 +0200
committerTheMelmacian <76712303+TheMelmacian@users.noreply.github.com>2026-05-30 16:33:59 +0200
commit7939f3b009e830e38a3f37455418011043429ee3 (patch)
tree1436c149f12c271c13fa9328757268644ddf3758
parent2a95223c6718bf8892369322b8a30a45e430739f (diff)
only fetch language codes for the requested library when generating filter values
-rw-r--r--Emby.Server.Implementations/Library/LibraryManager.cs12
-rw-r--r--Jellyfin.Api/Controllers/FilterController.cs38
-rw-r--r--Jellyfin.Server.Implementations/Item/BaseItemRepository.ByName.cs41
-rw-r--r--MediaBrowser.Controller/Library/ILibraryManager.cs8
-rw-r--r--MediaBrowser.Controller/Persistence/IItemRepository.cs9
5 files changed, 105 insertions, 3 deletions
diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs
index cc85f09d23..f075d2f649 100644
--- a/Emby.Server.Implementations/Library/LibraryManager.cs
+++ b/Emby.Server.Implementations/Library/LibraryManager.cs
@@ -3862,5 +3862,17 @@ namespace Emby.Server.Implementations.Library
{
return _mediaStreamRepository.GetMediaStreamLanguages(mediaStreamType);
}
+
+ /// <inheritdoc />
+ public IReadOnlyList<string> GetMediaStreamLanguages(MediaStreamType mediaStreamType, InternalItemsQuery query)
+ {
+ if (query.User is not null)
+ {
+ AddUserToQuery(query, query.User);
+ }
+
+ SetTopParentOrAncestorIds(query);
+ return _itemRepository.GetMediaStreamLanguages(query, mediaStreamType);
+ }
}
}
diff --git a/Jellyfin.Api/Controllers/FilterController.cs b/Jellyfin.Api/Controllers/FilterController.cs
index cfc8be28ae..07ebe83e86 100644
--- a/Jellyfin.Api/Controllers/FilterController.cs
+++ b/Jellyfin.Api/Controllers/FilterController.cs
@@ -158,13 +158,42 @@ public class FilterController : BaseJellyfinApiController
IsSeries = isSeries
};
+ var streamLanguageQuery = new InternalItemsQuery(user)
+ {
+ // It's possible that different langauges are only available on alternative versions.
+ // To fetch them all, owned items are inlcluded.
+ IncludeOwnedItems = true,
+ IncludeItemTypes = includeItemTypes,
+ DtoOptions = new DtoOptions
+ {
+ Fields = Array.Empty<ItemFields>(),
+ EnableImages = false,
+ EnableUserData = false
+ },
+ IsAiring = isAiring,
+ IsMovie = isMovie,
+ IsSports = isSports,
+ IsKids = isKids,
+ IsNews = isNews,
+ IsSeries = isSeries
+ };
+
if ((recursive ?? true) || parentItem is UserView || parentItem is ICollectionFolder)
{
genreQuery.AncestorIds = parentItem is null ? Array.Empty<Guid>() : new[] { parentItem.Id };
+ streamLanguageQuery.AncestorIds = parentItem is null ? Array.Empty<Guid>() : new[] { parentItem.Id };
}
else
{
genreQuery.Parent = parentItem;
+ streamLanguageQuery.Parent = parentItem;
+ }
+
+ if ((includeItemTypes.Contains(BaseItemKind.Series) || includeItemTypes.Contains(BaseItemKind.Season))
+ && !includeItemTypes.Contains(BaseItemKind.Episode))
+ {
+ // streams are joined on epsiodes not shows or seasons
+ streamLanguageQuery.IncludeItemTypes = [..includeItemTypes, BaseItemKind.Episode];
}
if (includeItemTypes.Length == 1
@@ -188,10 +217,13 @@ public class FilterController : BaseJellyfinApiController
}).ToArray();
}
- if (includeItemTypes.Contains(BaseItemKind.Movie) || includeItemTypes.Contains(BaseItemKind.Series))
+ if (includeItemTypes.Contains(BaseItemKind.Movie)
+ || includeItemTypes.Contains(BaseItemKind.Series)
+ || includeItemTypes.Contains(BaseItemKind.Season)
+ || includeItemTypes.Contains(BaseItemKind.Episode))
{
filters.AudioLanguages = _libraryManager
- .GetMediaStreamLanguages(MediaStreamType.Audio)
+ .GetMediaStreamLanguages(MediaStreamType.Audio, streamLanguageQuery)
.Select(language =>
{
var culture = _localization.FindLanguageInfo(language);
@@ -204,7 +236,7 @@ public class FilterController : BaseJellyfinApiController
.OrderBy(l => l.Name)
.ToArray();
filters.SubtitleLanguages = _libraryManager
- .GetMediaStreamLanguages(MediaStreamType.Subtitle)
+ .GetMediaStreamLanguages(MediaStreamType.Subtitle, streamLanguageQuery)
.Select(language =>
{
var culture = _localization.FindLanguageInfo(language);
diff --git a/Jellyfin.Server.Implementations/Item/BaseItemRepository.ByName.cs b/Jellyfin.Server.Implementations/Item/BaseItemRepository.ByName.cs
index e4fd3204e1..00ffd984f5 100644
--- a/Jellyfin.Server.Implementations/Item/BaseItemRepository.ByName.cs
+++ b/Jellyfin.Server.Implementations/Item/BaseItemRepository.ByName.cs
@@ -7,6 +7,7 @@ using Jellyfin.Data.Enums;
using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
using Microsoft.EntityFrameworkCore;
using BaseItemDto = MediaBrowser.Controller.Entities.BaseItem;
@@ -81,6 +82,46 @@ public sealed partial class BaseItemRepository
_itemTypeLookup.MusicGenreTypes);
}
+ /// <inheritdoc />
+ public IReadOnlyList<string> GetMediaStreamLanguages(InternalItemsQuery filter, MediaStreamType mediaStreamType)
+ {
+ ArgumentNullException.ThrowIfNull(filter);
+
+ if (!filter.Limit.HasValue)
+ {
+ filter.EnableTotalRecordCount = false;
+ }
+
+ using var context = _dbProvider.CreateDbContext();
+
+ return TranslateQuery(
+ context.BaseItems.Include(e => e.MediaStreams).Where(e => e.Id != EF.Constant(PlaceholderId)),
+ context,
+ new InternalItemsQuery(filter.User)
+ {
+ IncludeOwnedItems = filter.IncludeOwnedItems,
+ ExcludeItemTypes = filter.ExcludeItemTypes,
+ IncludeItemTypes = filter.IncludeItemTypes,
+ MediaTypes = filter.MediaTypes,
+ AncestorIds = filter.AncestorIds,
+ ItemIds = filter.ItemIds,
+ TopParentIds = filter.TopParentIds,
+ ParentId = filter.ParentId,
+ IsAiring = filter.IsAiring,
+ IsMovie = filter.IsMovie,
+ IsSports = filter.IsSports,
+ IsKids = filter.IsKids,
+ IsNews = filter.IsNews,
+ IsSeries = filter.IsSeries
+ })
+ .Where(e => e.MediaStreams != null)
+ .SelectMany(e => e.MediaStreams!)
+ .Where(e => e.StreamType == (MediaStreamTypeEntity)mediaStreamType)
+ .Select(s => string.IsNullOrEmpty(s.Language) ? "und" : s.Language) // und = undetermined
+ .Distinct()
+ .ToArray();
+ }
+
private string[] GetItemValueNames(IReadOnlyList<ItemValueType> itemValueTypes, IReadOnlyList<string> withItemTypes, IReadOnlyList<string> excludeItemTypes)
{
using var context = _dbProvider.CreateDbContext();
diff --git a/MediaBrowser.Controller/Library/ILibraryManager.cs b/MediaBrowser.Controller/Library/ILibraryManager.cs
index c23eba75ef..c37b13ea4f 100644
--- a/MediaBrowser.Controller/Library/ILibraryManager.cs
+++ b/MediaBrowser.Controller/Library/ILibraryManager.cs
@@ -800,5 +800,13 @@ namespace MediaBrowser.Controller.Library
/// <param name="mediaStreamType">The stream type.</param>
/// <returns>List of language codes.</returns>
IReadOnlyList<string> GetMediaStreamLanguages(MediaStreamType mediaStreamType);
+
+ /// <summary>
+ /// Gets a list of all language codes for the matching items and the the provided stream type.
+ /// </summary>
+ /// <param name="mediaStreamType">The stream type.</param>
+ /// <param name="query">The query filter.</param>
+ /// <returns>List of language codes.</returns>
+ IReadOnlyList<string> GetMediaStreamLanguages(MediaStreamType mediaStreamType, InternalItemsQuery query);
}
}
diff --git a/MediaBrowser.Controller/Persistence/IItemRepository.cs b/MediaBrowser.Controller/Persistence/IItemRepository.cs
index 291916ab25..d44fe57bed 100644
--- a/MediaBrowser.Controller/Persistence/IItemRepository.cs
+++ b/MediaBrowser.Controller/Persistence/IItemRepository.cs
@@ -7,6 +7,7 @@ using Jellyfin.Data.Enums;
using Jellyfin.Database.Implementations.Entities;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Dto;
+using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
namespace MediaBrowser.Controller.Persistence;
@@ -120,6 +121,14 @@ public interface IItemRepository
IReadOnlyList<string> GetGenreNames();
/// <summary>
+ /// Gets all language codes of the matching base items and the provided stream type.
+ /// </summary>
+ /// <param name="filter">The query filter.</param>
+ /// <param name="mediaStreamType">The type of the media stream.</param>
+ /// <returns>List of language codes.</returns>
+ public IReadOnlyList<string> GetMediaStreamLanguages(InternalItemsQuery filter, MediaStreamType mediaStreamType);
+
+ /// <summary>
/// Gets all artist names.
/// </summary>
/// <returns>The list of artist names.</returns>