aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2015-03-31 12:24:16 -0400
committerLuke Pulverenti <luke.pulverenti@gmail.com>2015-03-31 12:24:16 -0400
commita025f4eefaf43c27f33521239d99c47d292728f5 (patch)
treeff6cbf4d0eba8b58c3acdadbbc5fe0b895ff4a6a
parenteaf70589ae9469616596ee951e50e83941495b9e (diff)
sync updates
-rw-r--r--MediaBrowser.Api/BaseApiService.cs11
-rw-r--r--MediaBrowser.Api/Playback/BaseStreamingService.cs2
-rw-r--r--MediaBrowser.Api/Playback/MediaInfoService.cs62
-rw-r--r--MediaBrowser.Api/Playback/TranscodingThrottler.cs2
-rw-r--r--MediaBrowser.Api/UserLibrary/UserLibraryService.cs8
-rw-r--r--MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs8
-rw-r--r--MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs77
-rw-r--r--MediaBrowser.Dlna/Didl/DidlBuilder.cs4
-rw-r--r--MediaBrowser.Dlna/PlayTo/PlayToController.cs4
-rw-r--r--MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs2
-rw-r--r--MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs109
-rw-r--r--MediaBrowser.Model/Configuration/UserConfiguration.cs1
-rw-r--r--MediaBrowser.Model/Dlna/StreamBuilder.cs59
-rw-r--r--MediaBrowser.Model/Dlna/StreamInfo.cs74
-rw-r--r--MediaBrowser.Model/Entities/MediaStream.cs6
-rw-r--r--MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs9
-rw-r--r--MediaBrowser.Server.Implementations/Dto/DtoService.cs8
-rw-r--r--MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs31
-rw-r--r--MediaBrowser.Server.Implementations/Library/UserViewManager.cs2
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs6
-rw-r--r--MediaBrowser.Server.Implementations/Localization/Server/server.json1
-rw-r--r--MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs5
-rw-r--r--MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs4
-rw-r--r--MediaBrowser.Server.Startup.Common/ApplicationHost.cs2
24 files changed, 365 insertions, 132 deletions
diff --git a/MediaBrowser.Api/BaseApiService.cs b/MediaBrowser.Api/BaseApiService.cs
index 4465be97a..3364c3c6b 100644
--- a/MediaBrowser.Api/BaseApiService.cs
+++ b/MediaBrowser.Api/BaseApiService.cs
@@ -73,6 +73,17 @@ namespace MediaBrowser.Api
return ResultFactory.GetOptimizedResultUsingCache(Request, cacheKey, lastDateModified, cacheDuration, factoryFn);
}
+ /// <summary>
+ /// Infers the server address from the url
+ /// </summary>
+ /// <returns></returns>
+ protected string GetServerAddress()
+ {
+ var index = Request.AbsoluteUri.IndexOf(Request.PathInfo, StringComparison.OrdinalIgnoreCase);
+
+ return Request.AbsoluteUri.Substring(0, index);
+ }
+
protected void AssertCanUpdateUser(IUserManager userManager, string userId)
{
var auth = AuthorizationContext.GetAuthorizationInfo(Request);
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 8c4bcf0a3..75321f872 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -699,7 +699,7 @@ namespace MediaBrowser.Api.Playback
if (!string.IsNullOrEmpty(state.SubtitleStream.Language))
{
- var charenc = SubtitleEncoder.GetSubtitleFileCharacterSet(subtitlePath);
+ var charenc = SubtitleEncoder.GetSubtitleFileCharacterSet(subtitlePath, state.MediaSource.Protocol, CancellationToken.None).Result;
if (!string.IsNullOrEmpty(charenc))
{
diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs
index 6eba19545..0930c0002 100644
--- a/MediaBrowser.Api/Playback/MediaInfoService.cs
+++ b/MediaBrowser.Api/Playback/MediaInfoService.cs
@@ -59,6 +59,9 @@ namespace MediaBrowser.Api.Playback
[ApiMember(Name = "MediaSourceId", Description = "The media version id, if playing an alternate version", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
public string MediaSourceId { get; set; }
+
+ [ApiMember(Name = "LiveStreamId", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
+ public string LiveStreamId { get; set; }
}
[Route("/LiveStreams/Open", "POST", Summary = "Opens a media source")]
@@ -142,7 +145,7 @@ namespace MediaBrowser.Api.Playback
public async Task<object> Post(GetPostedPlaybackInfo request)
{
- var info = await GetPlaybackInfo(request.Id, request.UserId, request.MediaSourceId).ConfigureAwait(false);
+ var info = await GetPlaybackInfo(request.Id, request.UserId, request.MediaSourceId, request.LiveStreamId).ConfigureAwait(false);
var authInfo = AuthorizationContext.GetAuthorizationInfo(Request);
var profile = request.DeviceProfile;
@@ -164,29 +167,37 @@ namespace MediaBrowser.Api.Playback
return ToOptimizedResult(info);
}
- private async Task<PlaybackInfoResponse> GetPlaybackInfo(string id, string userId, string mediaSourceId = null)
+ private async Task<PlaybackInfoResponse> GetPlaybackInfo(string id, string userId, string mediaSourceId = null, string liveStreamId = null)
{
var result = new PlaybackInfoResponse();
- IEnumerable<MediaSourceInfo> mediaSources;
-
- try
- {
- mediaSources = await _mediaSourceManager.GetPlayackMediaSources(id, userId, true, CancellationToken.None).ConfigureAwait(false);
- }
- catch (PlaybackException ex)
+ if (string.IsNullOrWhiteSpace(liveStreamId))
{
- mediaSources = new List<MediaSourceInfo>();
- result.ErrorCode = ex.ErrorCode;
- }
+ IEnumerable<MediaSourceInfo> mediaSources;
+ try
+ {
+ mediaSources = await _mediaSourceManager.GetPlayackMediaSources(id, userId, true, CancellationToken.None).ConfigureAwait(false);
+ }
+ catch (PlaybackException ex)
+ {
+ mediaSources = new List<MediaSourceInfo>();
+ result.ErrorCode = ex.ErrorCode;
+ }
- result.MediaSources = mediaSources.ToList();
+ result.MediaSources = mediaSources.ToList();
- if (!string.IsNullOrWhiteSpace(mediaSourceId))
+ if (!string.IsNullOrWhiteSpace(mediaSourceId))
+ {
+ result.MediaSources = result.MediaSources
+ .Where(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase))
+ .ToList();
+ }
+ }
+ else
{
- result.MediaSources = result.MediaSources
- .Where(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase))
- .ToList();
+ var mediaSource = await _mediaSourceManager.GetLiveStream(liveStreamId, CancellationToken.None).ConfigureAwait(false);
+
+ result.MediaSources = new List<MediaSourceInfo> { mediaSource };
}
if (result.MediaSources.Count == 0)
@@ -236,6 +247,8 @@ namespace MediaBrowser.Api.Playback
{
var streamBuilder = new StreamBuilder();
+ var baseUrl = GetServerAddress();
+
var options = new VideoOptions
{
MediaSources = new List<MediaSourceInfo> { mediaSource },
@@ -275,7 +288,7 @@ namespace MediaBrowser.Api.Playback
if (streamInfo != null)
{
- SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token);
+ SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, baseUrl, auth.Token);
}
}
@@ -293,7 +306,7 @@ namespace MediaBrowser.Api.Playback
if (streamInfo != null)
{
- SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token);
+ SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, baseUrl, auth.Token);
}
}
@@ -307,21 +320,22 @@ namespace MediaBrowser.Api.Playback
if (streamInfo != null && streamInfo.PlayMethod == PlayMethod.Transcode)
{
streamInfo.StartPositionTicks = startTimeTicks;
- mediaSource.TranscodingUrl = streamInfo.ToUrl("-", auth.Token).TrimStart('-');
+ mediaSource.TranscodingUrl = streamInfo.ToUrl(baseUrl, auth.Token);
mediaSource.TranscodingContainer = streamInfo.Container;
mediaSource.TranscodingSubProtocol = streamInfo.SubProtocol;
}
if (streamInfo != null)
{
- SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token);
+ SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, baseUrl, auth.Token);
}
}
}
- private void SetDeviceSpecificSubtitleInfo(StreamInfo info, MediaSourceInfo mediaSource, string accessToken)
+ private void SetDeviceSpecificSubtitleInfo(StreamInfo info, MediaSourceInfo mediaSource, string baseUrl, string accessToken)
{
- var profiles = info.GetSubtitleProfiles(false, "-", accessToken);
+ var profiles = info.GetSubtitleProfiles(false, baseUrl, accessToken);
+ mediaSource.DefaultSubtitleStreamIndex = info.SubtitleStreamIndex;
foreach (var profile in profiles)
{
@@ -333,7 +347,7 @@ namespace MediaBrowser.Api.Playback
if (profile.DeliveryMethod == SubtitleDeliveryMethod.External)
{
- stream.DeliveryUrl = profile.Url.TrimStart('-');
+ stream.DeliveryUrl = profile.Url;
}
}
}
diff --git a/MediaBrowser.Api/Playback/TranscodingThrottler.cs b/MediaBrowser.Api/Playback/TranscodingThrottler.cs
index 58cfa086e..ff79bb48f 100644
--- a/MediaBrowser.Api/Playback/TranscodingThrottler.cs
+++ b/MediaBrowser.Api/Playback/TranscodingThrottler.cs
@@ -42,7 +42,7 @@ namespace MediaBrowser.Api.Playback
var options = GetOptions();
- if (options.EnableThrottling && IsThrottleAllowed(_job, options.ThrottleThresholdSeconds))
+ if (/*options.EnableThrottling &&*/ IsThrottleAllowed(_job, options.ThrottleThresholdSeconds))
{
PauseTranscoding();
}
diff --git a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
index cdfd00ce9..38eae2577 100644
--- a/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
+++ b/MediaBrowser.Api/UserLibrary/UserLibraryService.cs
@@ -304,6 +304,14 @@ namespace MediaBrowser.Api.UserLibrary
{
var user = _userManager.GetUserById(request.UserId);
+ if (!request.IsPlayed.HasValue)
+ {
+ if (user.Configuration.HidePlayedInLatest)
+ {
+ request.IsPlayed = false;
+ }
+ }
+
var list = _userViewManager.GetLatestItems(new LatestItemsQuery
{
GroupItems = request.GroupItems,
diff --git a/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs b/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs
index 37c2bf4d2..e4a2cd007 100644
--- a/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs
+++ b/MediaBrowser.Controller/MediaEncoding/ISubtitleEncoder.cs
@@ -1,4 +1,5 @@
-using System.IO;
+using MediaBrowser.Model.MediaInfo;
+using System.IO;
using System.Threading;
using System.Threading.Tasks;
@@ -47,8 +48,9 @@ namespace MediaBrowser.Controller.MediaEncoding
/// Gets the subtitle language encoding parameter.
/// </summary>
/// <param name="path">The path.</param>
+ /// <param name="protocol">The protocol.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>System.String.</returns>
- string GetSubtitleFileCharacterSet(string path);
-
+ Task<string> GetSubtitleFileCharacterSet(string path, MediaProtocol protocol, CancellationToken cancellationToken);
}
}
diff --git a/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs b/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs
index 57fddb2b1..a006a1723 100644
--- a/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs
+++ b/MediaBrowser.Controller/MediaEncoding/MediaStreamSelector.cs
@@ -41,8 +41,6 @@ namespace MediaBrowser.Controller.MediaEncoding
streams = GetSortedStreams(streams, MediaStreamType.Subtitle, preferredLanguages)
.ToList();
- var full = streams.Where(s => !s.IsForced);
-
MediaStream stream = null;
if (mode == SubtitlePlaybackMode.None)
@@ -55,13 +53,13 @@ namespace MediaBrowser.Controller.MediaEncoding
// if the audio language is not understood by the user, load their preferred subs, if there are any
if (!ContainsOrdinal(preferredLanguages, audioTrackLanguage))
{
- stream = full.FirstOrDefault(s => ContainsOrdinal(preferredLanguages, s.Language));
+ stream = streams.Where(s => !s.IsForced).FirstOrDefault(s => ContainsOrdinal(preferredLanguages, s.Language));
}
}
else if (mode == SubtitlePlaybackMode.Always)
{
// always load the most suitable full subtitles
- stream = full.FirstOrDefault();
+ stream = streams.FirstOrDefault(s => !s.IsForced);
}
// load forced subs if we have found no suitable full subtitles
@@ -97,6 +95,77 @@ namespace MediaBrowser.Controller.MediaEncoding
.ThenBy(i => i.Index);
}
+ public static void SetSubtitleStreamScores(List<MediaStream> streams,
+ List<string> preferredLanguages,
+ SubtitlePlaybackMode mode,
+ string audioTrackLanguage)
+ {
+ if (mode == SubtitlePlaybackMode.None)
+ {
+ return;
+ }
+
+ streams = GetSortedStreams(streams, MediaStreamType.Subtitle, preferredLanguages)
+ .ToList();
+
+ var filteredStreams = new List<MediaStream>();
+
+ if (mode == SubtitlePlaybackMode.Default)
+ {
+ // if the audio language is not understood by the user, load their preferred subs, if there are any
+ if (!ContainsOrdinal(preferredLanguages, audioTrackLanguage))
+ {
+ filteredStreams = streams.Where(s => !s.IsForced && ContainsOrdinal(preferredLanguages, s.Language))
+ .ToList();
+ }
+ }
+ else if (mode == SubtitlePlaybackMode.Always)
+ {
+ // always load the most suitable full subtitles
+ filteredStreams = streams.Where(s => !s.IsForced)
+ .ToList();
+ }
+
+ // load forced subs if we have found no suitable full subtitles
+ if (filteredStreams.Count == 0)
+ {
+ filteredStreams = streams
+ .Where(s => s.IsForced && string.Equals(s.Language, audioTrackLanguage, StringComparison.OrdinalIgnoreCase))
+ .ToList();
+ }
+
+ foreach (var stream in filteredStreams)
+ {
+ stream.Score = GetSubtitleScore(stream, preferredLanguages);
+ }
+ }
+
+ private static int GetSubtitleScore(MediaStream stream, List<string> languagePreferences)
+ {
+ var values = new List<int>();
+
+ var index = languagePreferences.FindIndex(l => string.Equals(stream.Language, l, StringComparison.OrdinalIgnoreCase));
+
+ values.Add(index == -1 ? 0 : 100 - index);
+
+ values.Add(stream.IsDefault ? 1 : 0);
+ values.Add(stream.SupportsExternalStream ? 1 : 0);
+ values.Add(stream.IsTextSubtitleStream ? 1 : 0);
+ values.Add(stream.IsExternal ? 1 : 0);
+
+ values.Reverse();
+ var scale = 1;
+ var score = 0;
+
+ foreach (var value in values)
+ {
+ score += scale * (value + 1);
+ scale *= 10;
+ }
+
+ return score;
+ }
+
private static int GetBooleanOrderBy(bool value)
{
return value ? 0 : 1;
diff --git a/MediaBrowser.Dlna/Didl/DidlBuilder.cs b/MediaBrowser.Dlna/Didl/DidlBuilder.cs
index b364414d1..3b1cdb542 100644
--- a/MediaBrowser.Dlna/Didl/DidlBuilder.cs
+++ b/MediaBrowser.Dlna/Didl/DidlBuilder.cs
@@ -124,7 +124,7 @@ namespace MediaBrowser.Dlna.Didl
{
if (streamInfo == null)
{
- var sources = _user == null ? video.GetMediaSources(true).ToList() : _mediaSourceManager.GetStaticMediaSources(video, true, _user).ToList();
+ var sources = _user == null ? _mediaSourceManager.GetStaticMediaSources(video, true).ToList() : _mediaSourceManager.GetStaticMediaSources(video, true, _user).ToList();
streamInfo = new StreamBuilder().BuildVideoItem(new VideoOptions
{
@@ -351,7 +351,7 @@ namespace MediaBrowser.Dlna.Didl
if (streamInfo == null)
{
- var sources = _user == null ? audio.GetMediaSources(true).ToList() : _mediaSourceManager.GetStaticMediaSources(audio, true, _user).ToList();
+ var sources = _user == null ? _mediaSourceManager.GetStaticMediaSources(audio, true).ToList() : _mediaSourceManager.GetStaticMediaSources(audio, true, _user).ToList();
streamInfo = new StreamBuilder().BuildAudioItem(new AudioOptions
{
diff --git a/MediaBrowser.Dlna/PlayTo/PlayToController.cs b/MediaBrowser.Dlna/PlayTo/PlayToController.cs
index 3eb091a19..38c0f71cc 100644
--- a/MediaBrowser.Dlna/PlayTo/PlayToController.cs
+++ b/MediaBrowser.Dlna/PlayTo/PlayToController.cs
@@ -467,10 +467,10 @@ namespace MediaBrowser.Dlna.PlayTo
var profile = _dlnaManager.GetProfile(deviceInfo.ToDeviceIdentification()) ??
_dlnaManager.GetDefaultProfile();
-
+
var hasMediaSources = item as IHasMediaSources;
var mediaSources = hasMediaSources != null
- ? (user == null ? hasMediaSources.GetMediaSources(true) : _mediaSourceManager.GetStaticMediaSources(hasMediaSources, true, user)).ToList()
+ ? (user == null ? _mediaSourceManager.GetStaticMediaSources(hasMediaSources, true) : _mediaSourceManager.GetStaticMediaSources(hasMediaSources, true, user)).ToList()
: new List<MediaSourceInfo>();
var playlistItem = GetPlaylistItem(item, mediaSources, profile, _session.DeviceId, mediaSourceId, audioStreamIndex, subtitleStreamIndex);
diff --git a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs
index 8266f4d3a..78ac92f25 100644
--- a/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/BaseEncoder.cs
@@ -951,7 +951,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
if (!string.IsNullOrEmpty(state.SubtitleStream.Language))
{
- var charenc = SubtitleEncoder.GetSubtitleFileCharacterSet(subtitlePath);
+ var charenc = SubtitleEncoder.GetSubtitleFileCharacterSet(subtitlePath, state.MediaSource.Protocol, CancellationToken.None).Result;
if (!string.IsNullOrEmpty(charenc))
{
diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
index 7d74c51ba..14d3e7284 100644
--- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs
@@ -1,6 +1,7 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding;
@@ -29,8 +30,10 @@ namespace MediaBrowser.MediaEncoding.Subtitles
private readonly IFileSystem _fileSystem;
private readonly IMediaEncoder _mediaEncoder;
private readonly IJsonSerializer _json;
+ private readonly IHttpClient _httpClient;
+ private readonly IMediaSourceManager _mediaSourceManager;
- public SubtitleEncoder(ILibraryManager libraryManager, ILogger logger, IApplicationPaths appPaths, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IJsonSerializer json)
+ public SubtitleEncoder(ILibraryManager libraryManager, ILogger logger, IApplicationPaths appPaths, IFileSystem fileSystem, IMediaEncoder mediaEncoder, IJsonSerializer json, IHttpClient httpClient, IMediaSourceManager mediaSourceManager)
{
_libraryManager = libraryManager;
_logger = logger;
@@ -38,6 +41,8 @@ namespace MediaBrowser.MediaEncoding.Subtitles
_fileSystem = fileSystem;
_mediaEncoder = mediaEncoder;
_json = json;
+ _httpClient = httpClient;
+ _mediaSourceManager = mediaSourceManager;
}
private string SubtitleCachePath
@@ -127,9 +132,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles
int subtitleStreamIndex,
CancellationToken cancellationToken)
{
- var item = (Video)_libraryManager.GetItemById(new Guid(itemId));
+ var mediaSources = await _mediaSourceManager.GetPlayackMediaSources(itemId, false, cancellationToken).ConfigureAwait(false);
- var mediaSource = item.GetMediaSources(false)
+ var mediaSource = mediaSources
.First(i => string.Equals(i.Id, mediaSourceId));
var subtitleStream = mediaSource.MediaStreams
@@ -149,20 +154,20 @@ namespace MediaBrowser.MediaEncoding.Subtitles
var fileInfo = await GetReadableFile(mediaSource.Path, inputFiles, mediaSource.Protocol, subtitleStream, cancellationToken).ConfigureAwait(false);
- var stream = await GetSubtitleStream(fileInfo.Item1, fileInfo.Item3).ConfigureAwait(false);
+ var stream = await GetSubtitleStream(fileInfo.Item1, fileInfo.Item2, fileInfo.Item4, cancellationToken).ConfigureAwait(false);
- return new Tuple<Stream, string>(stream, fileInfo.Item2);
+ return new Tuple<Stream, string>(stream, fileInfo.Item3);
}
- private async Task<Stream> GetSubtitleStream(string path, bool requiresCharset)
+ private async Task<Stream> GetSubtitleStream(string path, MediaProtocol protocol, bool requiresCharset, CancellationToken cancellationToken)
{
if (requiresCharset)
{
- var charset = GetSubtitleFileCharacterSet(path);
+ var charset = await GetSubtitleFileCharacterSet(path, protocol, cancellationToken).ConfigureAwait(false);
if (!string.IsNullOrEmpty(charset))
{
- using (var fs = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, true))
+ using (var fs = await GetStream(path, protocol, cancellationToken).ConfigureAwait(false))
{
using (var reader = new StreamReader(fs, GetEncoding(charset)))
{
@@ -196,7 +201,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
}
}
- private async Task<Tuple<string, string, bool>> GetReadableFile(string mediaPath,
+ private async Task<Tuple<string, MediaProtocol, string, bool>> GetReadableFile(string mediaPath,
string[] inputFiles,
MediaProtocol protocol,
MediaStream subtitleStream,
@@ -228,12 +233,12 @@ namespace MediaBrowser.MediaEncoding.Subtitles
}
// Extract
- var outputPath = GetSubtitleCachePath(mediaPath, subtitleStream.Index, "." + outputFormat);
+ var outputPath = GetSubtitleCachePath(mediaPath, protocol, subtitleStream.Index, "." + outputFormat);
await ExtractTextSubtitle(inputFiles, protocol, subtitleStream.Index, outputCodec, outputPath, cancellationToken)
.ConfigureAwait(false);
- return new Tuple<string, string, bool>(outputPath, outputFormat, false);
+ return new Tuple<string, MediaProtocol, string, bool>(outputPath, MediaProtocol.File, outputFormat, false);
}
var currentFormat = (Path.GetExtension(subtitleStream.Path) ?? subtitleStream.Codec)
@@ -242,14 +247,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles
if (GetReader(currentFormat, false) == null)
{
// Convert
- var outputPath = GetSubtitleCachePath(mediaPath, subtitleStream.Index, ".srt");
+ var outputPath = GetSubtitleCachePath(mediaPath, protocol, subtitleStream.Index, ".srt");
- await ConvertTextSubtitleToSrt(subtitleStream.Path, outputPath, cancellationToken).ConfigureAwait(false);
+ await ConvertTextSubtitleToSrt(subtitleStream.Path, protocol, outputPath, cancellationToken).ConfigureAwait(false);
- return new Tuple<string, string, bool>(outputPath, "srt", true);
+ return new Tuple<string, MediaProtocol, string, bool>(outputPath, MediaProtocol.File, "srt", true);
}
- return new Tuple<string, string, bool>(subtitleStream.Path, currentFormat, true);
+ return new Tuple<string, MediaProtocol, string, bool>(subtitleStream.Path, protocol, currentFormat, true);
}
private async Task<SubtitleTrackInfo> GetTrackInfo(Stream stream,
@@ -336,10 +341,11 @@ namespace MediaBrowser.MediaEncoding.Subtitles
/// Converts the text subtitle to SRT.
/// </summary>
/// <param name="inputPath">The input path.</param>
+ /// <param name="inputProtocol">The input protocol.</param>
/// <param name="outputPath">The output path.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- public async Task ConvertTextSubtitleToSrt(string inputPath, string outputPath, CancellationToken cancellationToken)
+ private async Task ConvertTextSubtitleToSrt(string inputPath, MediaProtocol inputProtocol, string outputPath, CancellationToken cancellationToken)
{
var semaphore = GetLock(outputPath);
@@ -349,7 +355,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
{
if (!File.Exists(outputPath))
{
- await ConvertTextSubtitleToSrtInternal(inputPath, outputPath).ConfigureAwait(false);
+ await ConvertTextSubtitleToSrtInternal(inputPath, inputProtocol, outputPath, cancellationToken).ConfigureAwait(false);
}
}
finally
@@ -362,13 +368,17 @@ namespace MediaBrowser.MediaEncoding.Subtitles
/// Converts the text subtitle to SRT internal.
/// </summary>
/// <param name="inputPath">The input path.</param>
+ /// <param name="inputProtocol">The input protocol.</param>
/// <param name="outputPath">The output path.</param>
+ /// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- /// <exception cref="System.ArgumentNullException">inputPath
+ /// <exception cref="System.ArgumentNullException">
+ /// inputPath
/// or
- /// outputPath</exception>
+ /// outputPath
+ /// </exception>
/// <exception cref="System.ApplicationException"></exception>
- private async Task ConvertTextSubtitleToSrtInternal(string inputPath, string outputPath)
+ private async Task ConvertTextSubtitleToSrtInternal(string inputPath, MediaProtocol inputProtocol, string outputPath, CancellationToken cancellationToken)
{
if (string.IsNullOrEmpty(inputPath))
{
@@ -382,7 +392,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
Directory.CreateDirectory(Path.GetDirectoryName(outputPath));
- var encodingParam = GetSubtitleFileCharacterSet(inputPath);
+ var encodingParam = await GetSubtitleFileCharacterSet(inputPath, inputProtocol, cancellationToken).ConfigureAwait(false);
if (!string.IsNullOrEmpty(encodingParam))
{
@@ -688,32 +698,41 @@ namespace MediaBrowser.MediaEncoding.Subtitles
}
}
- private string GetSubtitleCachePath(string mediaPath, int subtitleStreamIndex, string outputSubtitleExtension)
+ private string GetSubtitleCachePath(string mediaPath, MediaProtocol protocol, int subtitleStreamIndex, string outputSubtitleExtension)
{
- var ticksParam = string.Empty;
+ if (protocol == MediaProtocol.File)
+ {
+ var ticksParam = string.Empty;
+
+ var date = _fileSystem.GetLastWriteTimeUtc(mediaPath);
- var date = _fileSystem.GetLastWriteTimeUtc(mediaPath);
+ var filename = (mediaPath + "_" + subtitleStreamIndex.ToString(CultureInfo.InvariantCulture) + "_" + date.Ticks.ToString(CultureInfo.InvariantCulture) + ticksParam).GetMD5() + outputSubtitleExtension;
- var filename = (mediaPath + "_" + subtitleStreamIndex.ToString(CultureInfo.InvariantCulture) + "_" + date.Ticks.ToString(CultureInfo.InvariantCulture) + ticksParam).GetMD5() + outputSubtitleExtension;
+ var prefix = filename.Substring(0, 1);
+
+ return Path.Combine(SubtitleCachePath, prefix, filename);
+ }
+ else
+ {
+ var filename = (mediaPath + "_" + subtitleStreamIndex.ToString(CultureInfo.InvariantCulture)).GetMD5() + outputSubtitleExtension;
- var prefix = filename.Substring(0, 1);
+ var prefix = filename.Substring(0, 1);
- return Path.Combine(SubtitleCachePath, prefix, filename);
+ return Path.Combine(SubtitleCachePath, prefix, filename);
+ }
}
- /// <summary>
- /// Gets the subtitle language encoding param.
- /// </summary>
- /// <param name="path">The path.</param>
- /// <returns>System.String.</returns>
- public string GetSubtitleFileCharacterSet(string path)
+ public async Task<string> GetSubtitleFileCharacterSet(string path, MediaProtocol protocol, CancellationToken cancellationToken)
{
- if (GetFileEncoding(path).Equals(Encoding.UTF8))
+ if (protocol == MediaProtocol.File)
{
- return string.Empty;
+ if (GetFileEncoding(path).Equals(Encoding.UTF8))
+ {
+ return string.Empty;
+ }
}
- var charset = DetectCharset(path);
+ var charset = await DetectCharset(path, protocol, cancellationToken).ConfigureAwait(false);
if (!string.IsNullOrWhiteSpace(charset))
{
@@ -769,11 +788,11 @@ namespace MediaBrowser.MediaEncoding.Subtitles
}
}
- private string DetectCharset(string path)
+ private async Task<string> DetectCharset(string path, MediaProtocol protocol, CancellationToken cancellationToken)
{
try
{
- using (var file = _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
+ using (var file = await GetStream(path, protocol, cancellationToken).ConfigureAwait(false))
{
var detector = new CharsetDetector();
detector.Feed(file);
@@ -819,5 +838,19 @@ namespace MediaBrowser.MediaEncoding.Subtitles
// It's ok - anything aside from utf is ok since that's what we're looking for
return Encoding.Default;
}
+
+ private async Task<Stream> GetStream(string path, MediaProtocol protocol, CancellationToken cancellationToken)
+ {
+ if (protocol == MediaProtocol.Http)
+ {
+ return await _httpClient.Get(path, cancellationToken).ConfigureAwait(false);
+ }
+ if (protocol == MediaProtocol.File)
+ {
+ return _fileSystem.GetFileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
+ }
+
+ throw new ArgumentOutOfRangeException("protocol");
+ }
}
}
diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs
index a78161140..98641636a 100644
--- a/MediaBrowser.Model/Configuration/UserConfiguration.cs
+++ b/MediaBrowser.Model/Configuration/UserConfiguration.cs
@@ -54,6 +54,7 @@ namespace MediaBrowser.Model.Configuration
public string[] LatestItemsExcludes { get; set; }
public bool HasMigratedToPolicy { get; set; }
+ public bool HidePlayedInLatest { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="UserConfiguration" /> class.
diff --git a/MediaBrowser.Model/Dlna/StreamBuilder.cs b/MediaBrowser.Model/Dlna/StreamBuilder.cs
index 1cc37de57..b27138b4a 100644
--- a/MediaBrowser.Model/Dlna/StreamBuilder.cs
+++ b/MediaBrowser.Model/Dlna/StreamBuilder.cs
@@ -282,6 +282,49 @@ namespace MediaBrowser.Model.Dlna
return playMethods;
}
+ private int? GetDefaultSubtitleStreamIndex(MediaSourceInfo item, SubtitleProfile[] subtitleProfiles)
+ {
+ int highestScore = -1;
+
+ foreach (MediaStream stream in item.MediaStreams)
+ {
+ if (stream.Type == MediaStreamType.Subtitle && stream.Score.HasValue)
+ {
+ if (stream.Score.Value > highestScore)
+ {
+ highestScore = stream.Score.Value;
+ }
+ }
+ }
+
+ List<MediaStream> topStreams = new List<MediaStream>();
+ foreach (MediaStream stream in item.MediaStreams)
+ {
+ if (stream.Type == MediaStreamType.Subtitle && stream.Score.HasValue && stream.Score.Value == highestScore)
+ {
+ topStreams.Add(stream);
+ }
+ }
+
+ // If multiple streams have an equal score, try to pick the most efficient one
+ if (topStreams.Count > 1)
+ {
+ foreach (MediaStream stream in topStreams)
+ {
+ foreach (SubtitleProfile profile in subtitleProfiles)
+ {
+ if (profile.Method == SubtitleDeliveryMethod.External && StringHelper.EqualsIgnoreCase(profile.Format, stream.Codec))
+ {
+ return stream.Index;
+ }
+ }
+ }
+ }
+
+ // If no optimization panned out, just use the original default
+ return item.DefaultSubtitleStreamIndex;
+ }
+
private StreamInfo BuildVideoItem(MediaSourceInfo item, VideoOptions options)
{
StreamInfo playlistItem = new StreamInfo
@@ -294,7 +337,7 @@ namespace MediaBrowser.Model.Dlna
DeviceProfile = options.Profile
};
- playlistItem.SubtitleStreamIndex = options.SubtitleStreamIndex ?? item.DefaultSubtitleStreamIndex;
+ playlistItem.SubtitleStreamIndex = options.SubtitleStreamIndex ?? GetDefaultSubtitleStreamIndex(item, options.Profile.SubtitleProfiles);
MediaStream subtitleStream = playlistItem.SubtitleStreamIndex.HasValue ? item.GetMediaStream(MediaStreamType.Subtitle, playlistItem.SubtitleStreamIndex.Value) : null;
MediaStream audioStream = item.GetDefaultAudioStream(options.AudioStreamIndex ?? item.DefaultAudioStreamIndex);
@@ -618,6 +661,8 @@ namespace MediaBrowser.Model.Dlna
// Look for an external profile that matches the stream type (text/graphical)
foreach (SubtitleProfile profile in subtitleProfiles)
{
+ bool requiresConversion = !StringHelper.EqualsIgnoreCase(subtitleStream.Codec, profile.Format);
+
if (!profile.SupportsLanguage(subtitleStream.Language))
{
continue;
@@ -625,6 +670,11 @@ namespace MediaBrowser.Model.Dlna
if (profile.Method == SubtitleDeliveryMethod.External && subtitleStream.IsTextSubtitleStream == MediaStream.IsTextFormat(profile.Format))
{
+ if (!requiresConversion)
+ {
+ return profile;
+ }
+
if (subtitleStream.SupportsExternalStream)
{
return profile;
@@ -640,6 +690,8 @@ namespace MediaBrowser.Model.Dlna
foreach (SubtitleProfile profile in subtitleProfiles)
{
+ bool requiresConversion = !StringHelper.EqualsIgnoreCase(subtitleStream.Codec, profile.Format);
+
if (!profile.SupportsLanguage(subtitleStream.Language))
{
continue;
@@ -647,6 +699,11 @@ namespace MediaBrowser.Model.Dlna
if (profile.Method == SubtitleDeliveryMethod.Embed && subtitleStream.IsTextSubtitleStream == MediaStream.IsTextFormat(profile.Format))
{
+ if (!requiresConversion)
+ {
+ return profile;
+ }
+
return profile;
}
}
diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs
index 9bfa684be..3977a9ab0 100644
--- a/MediaBrowser.Model/Dlna/StreamInfo.cs
+++ b/MediaBrowser.Model/Dlna/StreamInfo.cs
@@ -217,9 +217,9 @@ namespace MediaBrowser.Model.Dlna
return list;
}
- public List<SubtitleStreamInfo> GetExternalSubtitles(bool includeSelectedTrackOnly, string baseUrl, string accessToken)
+ public List<SubtitleStreamInfo> GetExternalSubtitles(bool includeSelectedTrackOnly, bool enableAllProfiles, string baseUrl, string accessToken)
{
- List<SubtitleStreamInfo> list = GetSubtitleProfiles(includeSelectedTrackOnly, baseUrl, accessToken);
+ List<SubtitleStreamInfo> list = GetSubtitleProfiles(includeSelectedTrackOnly, enableAllProfiles, baseUrl, accessToken);
List<SubtitleStreamInfo> newList = new List<SubtitleStreamInfo>();
// First add the selected track
@@ -236,6 +236,11 @@ namespace MediaBrowser.Model.Dlna
public List<SubtitleStreamInfo> GetSubtitleProfiles(bool includeSelectedTrackOnly, string baseUrl, string accessToken)
{
+ return GetSubtitleProfiles(includeSelectedTrackOnly, false, baseUrl, accessToken);
+ }
+
+ public List<SubtitleStreamInfo> GetSubtitleProfiles(bool includeSelectedTrackOnly, bool enableAllProfiles, string baseUrl, string accessToken)
+ {
List<SubtitleStreamInfo> list = new List<SubtitleStreamInfo>();
// HLS will preserve timestamps so we can just grab the full subtitle stream
@@ -250,9 +255,7 @@ namespace MediaBrowser.Model.Dlna
{
if (stream.Type == MediaStreamType.Subtitle && stream.Index == SubtitleStreamIndex.Value)
{
- SubtitleStreamInfo info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks);
-
- list.Add(info);
+ AddSubtitleProfiles(list, stream, enableAllProfiles, baseUrl, accessToken, startPositionTicks);
}
}
}
@@ -263,9 +266,7 @@ namespace MediaBrowser.Model.Dlna
{
if (stream.Type == MediaStreamType.Subtitle && (!SubtitleStreamIndex.HasValue || stream.Index != SubtitleStreamIndex.Value))
{
- SubtitleStreamInfo info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks);
-
- list.Add(info);
+ AddSubtitleProfiles(list, stream, enableAllProfiles, baseUrl, accessToken, startPositionTicks);
}
}
}
@@ -273,44 +274,57 @@ namespace MediaBrowser.Model.Dlna
return list;
}
- private SubtitleStreamInfo GetSubtitleStreamInfo(MediaStream stream, string baseUrl, string accessToken, long startPositionTicks)
+ private void AddSubtitleProfiles(List<SubtitleStreamInfo> list, MediaStream stream, bool enableAllProfiles, string baseUrl, string accessToken, long startPositionTicks)
{
- SubtitleStreamInfo info = GetSubtitleStreamInfo(stream);
-
- if (info.DeliveryMethod == SubtitleDeliveryMethod.External)
+ if (enableAllProfiles)
{
- if (MediaSource.Protocol == MediaProtocol.Http)
- {
- info.Url = stream.Path;
- }
- else if (!string.IsNullOrEmpty(baseUrl))
+ foreach (SubtitleProfile profile in DeviceProfile.SubtitleProfiles)
{
- info.Url = string.Format("{0}/Videos/{1}/{2}/Subtitles/{3}/{4}/Stream.{5}",
- baseUrl,
- ItemId,
- MediaSourceId,
- StringHelper.ToStringCultureInvariant(stream.Index),
- StringHelper.ToStringCultureInvariant(startPositionTicks),
- SubtitleFormat);
+ SubtitleStreamInfo info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, new[] { profile });
+
+ list.Add(info);
}
}
+ else
+ {
+ SubtitleStreamInfo info = GetSubtitleStreamInfo(stream, baseUrl, accessToken, startPositionTicks, DeviceProfile.SubtitleProfiles);
- return info;
+ list.Add(info);
+ }
}
- private SubtitleStreamInfo GetSubtitleStreamInfo(MediaStream stream)
+ private SubtitleStreamInfo GetSubtitleStreamInfo(MediaStream stream, string baseUrl, string accessToken, long startPositionTicks, SubtitleProfile[] subtitleProfiles)
{
- SubtitleProfile subtitleProfile = StreamBuilder.GetSubtitleProfile(stream, DeviceProfile.SubtitleProfiles, Context);
-
- return new SubtitleStreamInfo
+ SubtitleProfile subtitleProfile = StreamBuilder.GetSubtitleProfile(stream, subtitleProfiles, Context);
+ SubtitleStreamInfo info = new SubtitleStreamInfo
{
IsForced = stream.IsForced,
Language = stream.Language,
Name = stream.Language ?? "Unknown",
- Format = SubtitleFormat,
+ Format = subtitleProfile.Format,
Index = stream.Index,
DeliveryMethod = subtitleProfile.Method
};
+
+ if (info.DeliveryMethod == SubtitleDeliveryMethod.External)
+ {
+ if (MediaSource.Protocol == MediaProtocol.File || !StringHelper.EqualsIgnoreCase(stream.Codec, subtitleProfile.Format))
+ {
+ info.Url = string.Format("{0}/Videos/{1}/{2}/Subtitles/{3}/{4}/Stream.{5}",
+ baseUrl,
+ ItemId,
+ MediaSourceId,
+ StringHelper.ToStringCultureInvariant(stream.Index),
+ StringHelper.ToStringCultureInvariant(startPositionTicks),
+ subtitleProfile.Format);
+ }
+ else
+ {
+ info.Url = stream.Path;
+ }
+ }
+
+ return info;
}
/// <summary>
diff --git a/MediaBrowser.Model/Entities/MediaStream.cs b/MediaBrowser.Model/Entities/MediaStream.cs
index 760829ebf..dfeed7450 100644
--- a/MediaBrowser.Model/Entities/MediaStream.cs
+++ b/MediaBrowser.Model/Entities/MediaStream.cs
@@ -131,6 +131,12 @@ namespace MediaBrowser.Model.Entities
public int Index { get; set; }
/// <summary>
+ /// Gets or sets the score.
+ /// </summary>
+ /// <value>The score.</value>
+ public int? Score { get; set; }
+
+ /// <summary>
/// Gets or sets a value indicating whether this instance is external.
/// </summary>
/// <value><c>true</c> if this instance is external; otherwise, <c>false</c>.</value>
diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs
index 2852f5719..0f092b554 100644
--- a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs
+++ b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs
@@ -6,15 +6,14 @@ using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Subtitles;
-using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Providers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using MediaBrowser.Model.Providers;
namespace MediaBrowser.Providers.MediaInfo
{
@@ -23,14 +22,16 @@ namespace MediaBrowser.Providers.MediaInfo
private readonly ILibraryManager _libraryManager;
private readonly IServerConfigurationManager _config;
private readonly ISubtitleManager _subtitleManager;
+ private readonly IMediaSourceManager _mediaSourceManager;
private readonly ILogger _logger;
- public SubtitleScheduledTask(ILibraryManager libraryManager, IServerConfigurationManager config, ISubtitleManager subtitleManager, ILogger logger)
+ public SubtitleScheduledTask(ILibraryManager libraryManager, IServerConfigurationManager config, ISubtitleManager subtitleManager, ILogger logger, IMediaSourceManager mediaSourceManager)
{
_libraryManager = libraryManager;
_config = config;
_subtitleManager = subtitleManager;
_logger = logger;
+ _mediaSourceManager = mediaSourceManager;
}
public string Name
@@ -107,7 +108,7 @@ namespace MediaBrowser.Providers.MediaInfo
(options.DownloadMovieSubtitles &&
video is Movie))
{
- var mediaStreams = video.GetMediaSources(false).First().MediaStreams;
+ var mediaStreams = _mediaSourceManager.GetStaticMediaSources(video, false).First().MediaStreams;
var downloadedLanguages = await new SubtitleDownloader(_logger,
_subtitleManager)
diff --git a/MediaBrowser.Server.Implementations/Dto/DtoService.cs b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
index 756ff6917..dc6f4a525 100644
--- a/MediaBrowser.Server.Implementations/Dto/DtoService.cs
+++ b/MediaBrowser.Server.Implementations/Dto/DtoService.cs
@@ -261,7 +261,7 @@ namespace MediaBrowser.Server.Implementations.Dto
{
if (user == null)
{
- dto.MediaSources = hasMediaSources.GetMediaSources(true).ToList();
+ dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(hasMediaSources, true).ToList();
}
else
{
@@ -269,7 +269,7 @@ namespace MediaBrowser.Server.Implementations.Dto
}
}
}
-
+
if (fields.Contains(ItemFields.Studios))
{
AttachStudios(dto, item);
@@ -1280,7 +1280,7 @@ namespace MediaBrowser.Server.Implementations.Dto
}
else
{
- mediaStreams = iHasMediaSources.GetMediaSources(true).First().MediaStreams;
+ mediaStreams = _mediaSourceManager().GetStaticMediaSources(iHasMediaSources, true).First().MediaStreams;
}
dto.MediaStreams = mediaStreams;
@@ -1453,7 +1453,7 @@ namespace MediaBrowser.Server.Implementations.Dto
var tvChannel = item as LiveTvChannel;
if (tvChannel != null)
{
- dto.MediaSources = tvChannel.GetMediaSources(true).ToList();
+ dto.MediaSources = _mediaSourceManager().GetStaticMediaSources(tvChannel, true).ToList();
}
var channelItem = item as IChannelItem;
diff --git a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs
index e832142a9..66eeb61f7 100644
--- a/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/MediaSourceManager.cs
@@ -135,6 +135,7 @@ namespace MediaBrowser.Server.Implementations.Library
IEnumerable<MediaSourceInfo> mediaSources;
var hasMediaSources = (IHasMediaSources)item;
+ User user = null;
if (string.IsNullOrWhiteSpace(userId))
{
@@ -142,7 +143,7 @@ namespace MediaBrowser.Server.Implementations.Library
}
else
{
- var user = _userManager.GetUserById(userId);
+ user = _userManager.GetUserById(userId);
mediaSources = GetStaticMediaSources(hasMediaSources, enablePathSubstitution, user);
}
@@ -154,6 +155,10 @@ namespace MediaBrowser.Server.Implementations.Library
foreach (var source in dynamicMediaSources)
{
+ if (user != null)
+ {
+ SetUserProperties(source, user);
+ }
if (source.Protocol == MediaProtocol.File)
{
source.SupportsDirectStream = File.Exists(source.Path);
@@ -225,6 +230,11 @@ namespace MediaBrowser.Server.Implementations.Library
return GetPlayackMediaSources(id, null, enablePathSubstitution, cancellationToken);
}
+ public MediaSourceInfo GetStaticMediaSource(IHasMediaSources item, string mediaSourceId, bool enablePathSubstitution)
+ {
+ return GetStaticMediaSources(item, enablePathSubstitution).FirstOrDefault(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase));
+ }
+
public IEnumerable<MediaSourceInfo> GetStaticMediaSources(IHasMediaSources item, bool enablePathSubstitution)
{
if (item == null)
@@ -288,6 +298,9 @@ namespace MediaBrowser.Server.Implementations.Library
preferredSubs,
user.Configuration.SubtitleMode,
audioLangage);
+
+ MediaStreamSelector.SetSubtitleStreamScores(source.MediaStreams, preferredSubs,
+ user.Configuration.SubtitleMode, audioLangage);
}
private IEnumerable<MediaSourceInfo> SortMediaSources(IEnumerable<MediaSourceInfo> sources)
@@ -311,11 +324,6 @@ namespace MediaBrowser.Server.Implementations.Library
.ToList();
}
- public MediaSourceInfo GetStaticMediaSource(IHasMediaSources item, string mediaSourceId, bool enablePathSubstitution)
- {
- return GetStaticMediaSources(item, enablePathSubstitution).FirstOrDefault(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase));
- }
-
private readonly ConcurrentDictionary<string, LiveStreamInfo> _openStreams = new ConcurrentDictionary<string, LiveStreamInfo>(StringComparer.OrdinalIgnoreCase);
private readonly SemaphoreSlim _liveStreamSemaphore = new SemaphoreSlim(1, 1);
@@ -428,9 +436,16 @@ namespace MediaBrowser.Server.Implementations.Library
try
{
- var tuple = GetProvider(id);
+ LiveStreamInfo current;
+ if (_openStreams.TryGetValue(id, out current))
+ {
+ if (current.MediaSource.RequiresClosing)
+ {
+ var tuple = GetProvider(id);
- await tuple.Item1.CloseMediaSource(tuple.Item2, cancellationToken).ConfigureAwait(false);
+ await tuple.Item1.CloseMediaSource(tuple.Item2, cancellationToken).ConfigureAwait(false);
+ }
+ }
LiveStreamInfo removed;
if (_openStreams.TryRemove(id, out removed))
diff --git a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs
index e63a27551..757f08562 100644
--- a/MediaBrowser.Server.Implementations/Library/UserViewManager.cs
+++ b/MediaBrowser.Server.Implementations/Library/UserViewManager.cs
@@ -215,7 +215,7 @@ namespace MediaBrowser.Server.Implementations.Library
if (request.IsPlayed.HasValue)
{
var val = request.IsPlayed.Value;
- if (i.IsPlayed(currentUser) != val)
+ if (i is Video && i.IsPlayed(currentUser) != val)
{
return false;
}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
index 5de4cf499..d549cad46 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
@@ -17,11 +17,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv
private readonly ILiveTvManager _liveTvManager;
private readonly IJsonSerializer _jsonSerializer;
private readonly ILogger _logger;
+ private readonly IMediaSourceManager _mediaSourceManager;
- public LiveTvMediaSourceProvider(ILiveTvManager liveTvManager, IJsonSerializer jsonSerializer, ILogManager logManager)
+ public LiveTvMediaSourceProvider(ILiveTvManager liveTvManager, IJsonSerializer jsonSerializer, ILogManager logManager, IMediaSourceManager mediaSourceManager)
{
_liveTvManager = liveTvManager;
_jsonSerializer = jsonSerializer;
+ _mediaSourceManager = mediaSourceManager;
_logger = logManager.GetLogger(GetType().Name);
}
@@ -63,7 +65,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
{
var hasMediaSources = (IHasMediaSources)item;
- sources = hasMediaSources.GetMediaSources(false)
+ sources = _mediaSourceManager.GetStaticMediaSources(hasMediaSources, false)
.ToList();
}
diff --git a/MediaBrowser.Server.Implementations/Localization/Server/server.json b/MediaBrowser.Server.Implementations/Localization/Server/server.json
index f52d8a9fe..0cff99c5d 100644
--- a/MediaBrowser.Server.Implementations/Localization/Server/server.json
+++ b/MediaBrowser.Server.Implementations/Localization/Server/server.json
@@ -52,6 +52,7 @@
"HeaderAddUser": "Add User",
"LabelAddConnectSupporterHelp": "To add a user who isn't listed, you'll need to first link their account to Emby Connect from their user profile page.",
"LabelPinCode": "Pin code:",
+ "OptionHideWatchedContentFromLatestMedia": "Hide watched content from latest media",
"ButtonOk": "Ok",
"ButtonCancel": "Cancel",
"ButtonExit": "Exit",
diff --git a/MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs b/MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs
index 43fb10df0..73400f834 100644
--- a/MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs
+++ b/MediaBrowser.Server.Implementations/Sync/CloudSyncProfile.cs
@@ -198,8 +198,7 @@ namespace MediaBrowser.Server.Implementations.Sync
var maxAudioChannels = supportsAc3 || supportsDca ? "5" : "2";
codecProfiles.Add(new CodecProfile
{
- Type = CodecType.Audio,
- Codec = "mpeg4",
+ Type = CodecType.VideoAudio,
Conditions = new[]
{
new ProfileCondition
@@ -207,7 +206,7 @@ namespace MediaBrowser.Server.Implementations.Sync
Condition = ProfileConditionType.LessThanEqual,
Property = ProfileConditionValue.AudioChannels,
Value = maxAudioChannels,
- IsRequired = false
+ IsRequired = true
},
new ProfileCondition
{
diff --git a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs
index 7eb015ae7..271b2bb39 100644
--- a/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs
+++ b/MediaBrowser.Server.Implementations/Sync/SyncJobProcessor.cs
@@ -495,7 +495,7 @@ namespace MediaBrowser.Server.Implementations.Sync
// No sense creating external subs if we're already burning one into the video
var externalSubs = streamInfo.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode ?
new List<SubtitleStreamInfo>() :
- streamInfo.GetExternalSubtitles(false, null, null);
+ streamInfo.GetExternalSubtitles(false, true, null, null);
// Mark as requiring conversion if transcoding the video, or if any subtitles need to be extracted
var requiresVideoTranscoding = streamInfo.PlayMethod == PlayMethod.Transcode && jobOptions.IsConverting;
@@ -823,7 +823,7 @@ namespace MediaBrowser.Server.Implementations.Sync
var hasMediaSources = item as IHasMediaSources;
- var mediaSources = hasMediaSources.GetMediaSources(false).ToList();
+ var mediaSources = _mediaSourceManager.GetStaticMediaSources(hasMediaSources, false).ToList();
var preferredAudio = string.IsNullOrEmpty(user.Configuration.AudioLanguagePreference)
? new string[] { }
diff --git a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
index aad88d022..df7b3f061 100644
--- a/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
+++ b/MediaBrowser.Server.Startup.Common/ApplicationHost.cs
@@ -530,7 +530,7 @@ namespace MediaBrowser.Server.Startup.Common
RegisterSingleInstance<ISessionContext>(new SessionContext(UserManager, authContext, SessionManager));
RegisterSingleInstance<IAuthService>(new AuthService(UserManager, authContext, ServerConfigurationManager, ConnectManager, SessionManager, DeviceManager));
- SubtitleEncoder = new SubtitleEncoder(LibraryManager, LogManager.GetLogger("SubtitleEncoder"), ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer);
+ SubtitleEncoder = new SubtitleEncoder(LibraryManager, LogManager.GetLogger("SubtitleEncoder"), ApplicationPaths, FileSystemManager, MediaEncoder, JsonSerializer, HttpClient, MediaSourceManager);
RegisterSingleInstance(SubtitleEncoder);
await ConfigureDisplayPreferencesRepositories().ConfigureAwait(false);