From d4d10f6e433cc472c5aafe6af53a101bba36bf79 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Mon, 12 May 2014 18:30:32 -0400 Subject: add new subtitle preferences --- .../Dto/DtoService.cs | 20 +++- .../Dto/MediaStreamSelector.cs | 102 +++++++++++++++++++++ .../Localization/Server/server.json | 7 ++ .../MediaBrowser.Server.Implementations.csproj | 1 + .../Session/HttpSessionController.cs | 5 - .../Session/SessionManager.cs | 25 +---- .../Session/WebSocketController.cs | 8 -- 7 files changed, 131 insertions(+), 37 deletions(-) create mode 100644 MediaBrowser.Server.Implementations/Dto/MediaStreamSelector.cs (limited to 'MediaBrowser.Server.Implementations') diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs index 38d6034e4..bf77f1869 100644 --- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs +++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs @@ -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); } } diff --git a/MediaBrowser.Server.Implementations/Dto/MediaStreamSelector.cs b/MediaBrowser.Server.Implementations/Dto/MediaStreamSelector.cs new file mode 100644 index 000000000..e5a859cdc --- /dev/null +++ b/MediaBrowser.Server.Implementations/Dto/MediaStreamSelector.cs @@ -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 streams, IEnumerable 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 streams, + IEnumerable preferredLanguages, + SubtitlePlaybackMode mode, + string audioTrackLanguage) + { + var languages = preferredLanguages as List ?? 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 list, string item) + { + return list.Any(i => string.Equals(i, item, StringComparison.OrdinalIgnoreCase)); + } + + private static IEnumerable GetSortedStreams(IEnumerable streams, MediaStreamType type, List 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(); + } + } +} diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json index 9e1943131..9ff395b7e 100644 --- a/MediaBrowser.Server.Implementations/Localization/Server/server.json +++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json @@ -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", diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj index 78d8da70d..2a1492c1f 100644 --- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj +++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj @@ -111,6 +111,7 @@ + diff --git a/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs b/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs index 024b0ec90..8d6289217 100644 --- a/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs +++ b/MediaBrowser.Server.Implementations/Session/HttpSessionController.cs @@ -37,11 +37,6 @@ namespace MediaBrowser.Server.Implementations.Session _postUrl = postUrl; } - public bool SupportsMediaRemoteControl - { - get { return false; } - } - public bool IsSessionActive { get diff --git a/MediaBrowser.Server.Implementations/Session/SessionManager.cs b/MediaBrowser.Server.Implementations/Session/SessionManager.cs index d2a047b42..cf27df70d 100644 --- a/MediaBrowser.Server.Implementations/Session/SessionManager.cs +++ b/MediaBrowser.Server.Implementations/Session/SessionManager.cs @@ -704,24 +704,6 @@ namespace MediaBrowser.Server.Implementations.Session return session; } - /// - /// Gets the session for remote control. - /// - /// The session id. - /// SessionInfo. - /// - 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, diff --git a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs index 3b6ecd21e..0edd57d2a 100644 --- a/MediaBrowser.Server.Implementations/Session/WebSocketController.cs +++ b/MediaBrowser.Server.Implementations/Session/WebSocketController.cs @@ -27,14 +27,6 @@ namespace MediaBrowser.Server.Implementations.Session Sockets = new List(); } - public bool SupportsMediaRemoteControl - { - get - { - return Sockets.Any(i => i.State == WebSocketState.Open); - } - } - public bool IsSessionActive { get -- cgit v1.2.3