mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-03-27 20:41:54 +00:00
add new subtitle preferences
This commit is contained in:
@@ -113,10 +113,26 @@ namespace MediaBrowser.Server.Implementations.Dto
|
||||
|
||||
if (user != null && dto.MediaSources != null && item is Video)
|
||||
{
|
||||
var preferredAudio = string.IsNullOrEmpty(user.Configuration.AudioLanguagePreference)
|
||||
? new string[] { }
|
||||
: new[] { user.Configuration.AudioLanguagePreference };
|
||||
|
||||
var preferredSubs = string.IsNullOrEmpty(user.Configuration.SubtitleLanguagePreference)
|
||||
? new string[] { }
|
||||
: new[] { user.Configuration.SubtitleLanguagePreference };
|
||||
|
||||
foreach (var source in dto.MediaSources)
|
||||
{
|
||||
//source.DefaultAudioStreamIndex = GetDefaultAudioStreamIndex(source, user.Configuration);
|
||||
//source.DefaultSubtitleStreamIndex = GetDefaultSubtitleStreamIndex(source, user.Configuration);
|
||||
source.DefaultAudioStreamIndex = MediaStreamSelector.GetDefaultAudioStreamIndex(
|
||||
source.MediaStreams, preferredAudio, user.Configuration.PlayDefaultAudioTrack);
|
||||
|
||||
var defaultAudioIndex = source.DefaultAudioStreamIndex;
|
||||
var audioLangage = defaultAudioIndex == null
|
||||
? null
|
||||
: source.MediaStreams.Where(i => i.Type == MediaStreamType.Audio && i.Index == defaultAudioIndex).Select(i => i.Language).FirstOrDefault();
|
||||
|
||||
source.DefaultSubtitleStreamIndex = MediaStreamSelector.GetDefaultSubtitleStreamIndex(source.MediaStreams, preferredSubs,
|
||||
user.Configuration.SubtitleMode, audioLangage);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
102
MediaBrowser.Server.Implementations/Dto/MediaStreamSelector.cs
Normal file
102
MediaBrowser.Server.Implementations/Dto/MediaStreamSelector.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace MediaBrowser.Server.Implementations.Dto
|
||||
{
|
||||
public static class MediaStreamSelector
|
||||
{
|
||||
public static int? GetDefaultAudioStreamIndex(List<MediaStream> streams, IEnumerable<string> preferredLanguages, bool preferDefaultTrack)
|
||||
{
|
||||
streams = GetSortedStreams(streams, MediaStreamType.Audio, preferredLanguages.ToList())
|
||||
.ToList();
|
||||
|
||||
if (preferDefaultTrack)
|
||||
{
|
||||
var defaultStream = streams.FirstOrDefault(i => i.IsDefault);
|
||||
|
||||
if (defaultStream != null)
|
||||
{
|
||||
return defaultStream.Index;
|
||||
}
|
||||
}
|
||||
|
||||
var stream = streams.FirstOrDefault();
|
||||
|
||||
if (stream != null)
|
||||
{
|
||||
return stream.Index;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static int? GetDefaultSubtitleStreamIndex(List<MediaStream> streams,
|
||||
IEnumerable<string> preferredLanguages,
|
||||
SubtitlePlaybackMode mode,
|
||||
string audioTrackLanguage)
|
||||
{
|
||||
var languages = preferredLanguages as List<string> ?? preferredLanguages.ToList();
|
||||
streams = GetSortedStreams(streams, MediaStreamType.Subtitle, languages).ToList();
|
||||
|
||||
var full = streams.Where(s => !s.IsForced);
|
||||
var forced = streams.Where(s => s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
MediaStream stream = null;
|
||||
|
||||
if (mode == SubtitlePlaybackMode.None)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (mode == SubtitlePlaybackMode.Default)
|
||||
{
|
||||
// if the audio language is not understood by the user, load their preferred subs, if there are any
|
||||
if (!ContainsOrdinal(languages, audioTrackLanguage))
|
||||
{
|
||||
stream = full.FirstOrDefault(s => ContainsOrdinal(languages, s.Language));
|
||||
}
|
||||
}
|
||||
else if (mode == SubtitlePlaybackMode.Always)
|
||||
{
|
||||
// always load the most suitable full subtitles
|
||||
stream = full.FirstOrDefault();
|
||||
}
|
||||
|
||||
// load forced subs if we have found no suitable full subtitles
|
||||
stream = stream ?? forced.FirstOrDefault();
|
||||
|
||||
if (stream != null)
|
||||
{
|
||||
return stream.Index;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static bool ContainsOrdinal(IEnumerable<string> list, string item)
|
||||
{
|
||||
return list.Any(i => string.Equals(i, item, StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
private static IEnumerable<MediaStream> GetSortedStreams(IEnumerable<MediaStream> streams, MediaStreamType type, List<string> languagePreferences)
|
||||
{
|
||||
var orderStreams = streams
|
||||
.Where(i => i.Type == type);
|
||||
|
||||
if (languagePreferences.Count == 0)
|
||||
{
|
||||
return orderStreams.OrderBy(i => i.IsDefault)
|
||||
.ThenBy(i => i.Index)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
return orderStreams.OrderBy(i => languagePreferences.FindIndex(l => string.Equals(i.Language, l, StringComparison.OrdinalIgnoreCase)))
|
||||
.ThenBy(i => i.IsDefault)
|
||||
.ThenBy(i => i.Index)
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,6 +64,13 @@
|
||||
"LabelAudioLanguagePreference": "Audio language preference:",
|
||||
"LabelSubtitleLanguagePreference": "Subtitle language preference:",
|
||||
"OptionDefaultSubtitles": "Default",
|
||||
"OptionOnlyForcedSubtitles": "Only forced subtitles",
|
||||
"OptionAlwaysPlaySubtitles": "Always play subtitles",
|
||||
"OptionNoSubtitles": "None",
|
||||
"OptionDefaultSubtitlesHelp": "Subtitles matching the language preference will be loaded when the audio is in a foreign language.",
|
||||
"OptionOnlyForcedSubtitlesHelp": "Only subtitles marked as forced will be loaded.",
|
||||
"OptionAlwaysPlaySubtitlesHelp": "Subtitles matching the language preference will be loaded regardless of the audio language.",
|
||||
"OptionNoSubtitlesHelp": "Subtitles will not be loaded by default.",
|
||||
"TabProfiles": "Profiles",
|
||||
"TabSecurity": "Security",
|
||||
"ButtonAddUser": "Add User",
|
||||
|
||||
@@ -111,6 +111,7 @@
|
||||
<Compile Include="Drawing\PlayedIndicatorDrawer.cs" />
|
||||
<Compile Include="Drawing\UnplayedCountIndicator.cs" />
|
||||
<Compile Include="Dto\DtoService.cs" />
|
||||
<Compile Include="Dto\MediaStreamSelector.cs" />
|
||||
<Compile Include="EntryPoints\AutomaticRestartEntryPoint.cs" />
|
||||
<Compile Include="EntryPoints\ExternalPortForwarding.cs" />
|
||||
<Compile Include="EntryPoints\LibraryChangedNotifier.cs" />
|
||||
|
||||
@@ -37,11 +37,6 @@ namespace MediaBrowser.Server.Implementations.Session
|
||||
_postUrl = postUrl;
|
||||
}
|
||||
|
||||
public bool SupportsMediaRemoteControl
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
public bool IsSessionActive
|
||||
{
|
||||
get
|
||||
|
||||
@@ -704,24 +704,6 @@ namespace MediaBrowser.Server.Implementations.Session
|
||||
return session;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the session for remote control.
|
||||
/// </summary>
|
||||
/// <param name="sessionId">The session id.</param>
|
||||
/// <returns>SessionInfo.</returns>
|
||||
/// <exception cref="ResourceNotFoundException"></exception>
|
||||
private SessionInfo GetSessionForRemoteControl(string sessionId)
|
||||
{
|
||||
var session = GetSession(sessionId);
|
||||
|
||||
if (!session.SupportsRemoteControl)
|
||||
{
|
||||
throw new ArgumentException(string.Format("Session {0} does not support remote control.", session.Id));
|
||||
}
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
public Task SendMessageCommand(string controllingSessionId, string sessionId, MessageCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
var generalCommand = new GeneralCommand
|
||||
@@ -742,7 +724,7 @@ namespace MediaBrowser.Server.Implementations.Session
|
||||
|
||||
public Task SendGeneralCommand(string controllingSessionId, string sessionId, GeneralCommand command, CancellationToken cancellationToken)
|
||||
{
|
||||
var session = GetSessionForRemoteControl(sessionId);
|
||||
var session = GetSession(sessionId);
|
||||
|
||||
var controllingSession = GetSession(controllingSessionId);
|
||||
AssertCanControl(session, controllingSession);
|
||||
@@ -752,7 +734,7 @@ namespace MediaBrowser.Server.Implementations.Session
|
||||
|
||||
public Task SendPlayCommand(string controllingSessionId, string sessionId, PlayRequest command, CancellationToken cancellationToken)
|
||||
{
|
||||
var session = GetSessionForRemoteControl(sessionId);
|
||||
var session = GetSession(sessionId);
|
||||
|
||||
var user = session.UserId.HasValue ? _userManager.GetUserById(session.UserId.Value) : null;
|
||||
|
||||
@@ -886,7 +868,7 @@ namespace MediaBrowser.Server.Implementations.Session
|
||||
|
||||
public Task SendPlaystateCommand(string controllingSessionId, string sessionId, PlaystateRequest command, CancellationToken cancellationToken)
|
||||
{
|
||||
var session = GetSessionForRemoteControl(sessionId);
|
||||
var session = GetSession(sessionId);
|
||||
|
||||
var controllingSession = GetSession(controllingSessionId);
|
||||
AssertCanControl(session, controllingSession);
|
||||
@@ -1157,7 +1139,6 @@ namespace MediaBrowser.Server.Implementations.Session
|
||||
Id = session.Id,
|
||||
LastActivityDate = session.LastActivityDate,
|
||||
NowPlayingPositionTicks = session.PlayState.PositionTicks,
|
||||
SupportsRemoteControl = session.SupportsRemoteControl,
|
||||
IsPaused = session.PlayState.IsPaused,
|
||||
IsMuted = session.PlayState.IsMuted,
|
||||
NowViewingItem = session.NowViewingItem,
|
||||
|
||||
@@ -27,14 +27,6 @@ namespace MediaBrowser.Server.Implementations.Session
|
||||
Sockets = new List<IWebSocketConnection>();
|
||||
}
|
||||
|
||||
public bool SupportsMediaRemoteControl
|
||||
{
|
||||
get
|
||||
{
|
||||
return Sockets.Any(i => i.State == WebSocketState.Open);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsSessionActive
|
||||
{
|
||||
get
|
||||
|
||||
Reference in New Issue
Block a user