diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2014-06-14 14:24:20 -0400 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2014-06-14 14:24:20 -0400 |
| commit | 0b60e7ca67394b24f4f1725b7d43405387c3e067 (patch) | |
| tree | 27de71b817df95686f9b5dae39ed2c68ac8a29fc /MediaBrowser.Controller | |
| parent | ffc4db41282be2d0762cbd198f14bbe0c9bd1540 (diff) | |
fixes #843 - Update Dlna to respect user audio/subtitle language settings
Diffstat (limited to 'MediaBrowser.Controller')
3 files changed, 158 insertions, 1 deletions
diff --git a/MediaBrowser.Controller/Entities/IHasMediaSources.cs b/MediaBrowser.Controller/Entities/IHasMediaSources.cs index 0b0dd1bf8..da040f296 100644 --- a/MediaBrowser.Controller/Entities/IHasMediaSources.cs +++ b/MediaBrowser.Controller/Entities/IHasMediaSources.cs @@ -1,5 +1,9 @@ -using MediaBrowser.Model.Dto; +using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Model.Dto; +using MediaBrowser.Model.Entities; +using System; using System.Collections.Generic; +using System.Linq; namespace MediaBrowser.Controller.Entities { @@ -12,4 +16,53 @@ namespace MediaBrowser.Controller.Entities /// <returns>Task{IEnumerable{MediaSourceInfo}}.</returns> IEnumerable<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution); } + + public static class HasMediaSourceExtensions + { + public static IEnumerable<MediaSourceInfo> GetMediaSources(this IHasMediaSources item, bool enablePathSubstitution, User user) + { + if (item == null) + { + throw new ArgumentNullException("item"); + } + + if (!(item is Video)) + { + return item.GetMediaSources(enablePathSubstitution); + } + + if (user == null) + { + throw new ArgumentNullException("user"); + } + + var sources = item.GetMediaSources(enablePathSubstitution).ToList(); + + 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 sources) + { + 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); + } + + return sources; + } + } } diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index addcaea8d..5f3a06f79 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -192,6 +192,7 @@ <Compile Include="MediaEncoding\IMediaEncoder.cs" /> <Compile Include="MediaEncoding\InternalMediaInfoResult.cs" /> <Compile Include="MediaEncoding\ISubtitleEncoder.cs" /> + <Compile Include="MediaEncoding\MediaStreamSelector.cs" /> <Compile Include="MediaEncoding\VideoEncodingOptions.cs" /> <Compile Include="Net\IHasResultFactory.cs" /> <Compile Include="Net\IHttpResultFactory.cs" /> diff --git a/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs b/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs new file mode 100644 index 000000000..58a68c257 --- /dev/null +++ b/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs @@ -0,0 +1,103 @@ +using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Entities; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace MediaBrowser.Controller.MediaEncoding +{ + 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.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); + + // Give some preferance to external text subs for better performance + return orderStreams.OrderBy(i => + { + var index = languagePreferences.FindIndex(l => string.Equals(i.Language, l, StringComparison.OrdinalIgnoreCase)); + + return index == -1 ? 100 : index; + }) + .ThenBy(i => i.IsDefault) + .ThenBy(i => i.IsTextSubtitleStream) + .ThenBy(i => i.IsExternal) + .ThenBy(i => i.Index) + .ToList(); + } + } +} |
