diff --git a/MediaBrowser.Api/LiveTv/LiveTvService.cs b/MediaBrowser.Api/LiveTv/LiveTvService.cs
index 9c11050823..5b821df0bd 100644
--- a/MediaBrowser.Api/LiveTv/LiveTvService.cs
+++ b/MediaBrowser.Api/LiveTv/LiveTvService.cs
@@ -104,6 +104,26 @@ namespace MediaBrowser.Api.LiveTv
[ApiMember(Name = "EnableUserData", Description = "Optional, include user data", IsRequired = false, DataType = "boolean", ParameterType = "query", Verb = "GET")]
public bool? EnableUserData { get; set; }
+ public string SortBy { get; set; }
+
+ public SortOrder? SortOrder { get; set; }
+
+ ///
+ /// Gets the order by.
+ ///
+ /// IEnumerable{ItemSortBy}.
+ public string[] GetOrderBy()
+ {
+ var val = SortBy;
+
+ if (string.IsNullOrEmpty(val))
+ {
+ return new string[] { };
+ }
+
+ return val.Split(',');
+ }
+
public GetChannels()
{
AddCurrentProgram = true;
@@ -650,6 +670,8 @@ namespace MediaBrowser.Api.LiveTv
{
public string Id { get; set; }
public string Container { get; set; }
+ public long T { get; set; }
+ public long S { get; set; }
}
public class LiveTvService : BaseApiService
@@ -681,9 +703,35 @@ namespace MediaBrowser.Api.LiveTv
outputHeaders["Content-Type"] = MimeTypes.GetMimeType(filePath);
+ long startPosition = 0;
+
+ if (request.T > 0)
+ {
+ var now = DateTime.UtcNow;
+
+ var totalTicks = now.Ticks - request.S;
+
+ if (totalTicks > 0)
+ {
+ double requestedOffset = request.T;
+ requestedOffset = Math.Max(0, requestedOffset - TimeSpan.FromSeconds(10).Ticks);
+
+ var pct = requestedOffset / totalTicks;
+
+ Logger.Info("Live stream offset pct {0}", pct);
+
+ var bytes = new FileInfo(filePath).Length;
+ Logger.Info("Live stream total bytes {0}", bytes);
+ startPosition = Convert.ToInt64(pct * bytes);
+ }
+ }
+
+ Logger.Info("Live stream starting byte position {0}", startPosition);
+
var streamSource = new ProgressiveFileCopier(_fileSystem, filePath, outputHeaders, null, Logger, CancellationToken.None)
{
- AllowEndOfFile = false
+ AllowEndOfFile = false,
+ StartPosition = startPosition
};
return ResultFactory.GetAsyncStreamWriter(streamSource);
@@ -848,6 +896,8 @@ namespace MediaBrowser.Api.LiveTv
IsNews = request.IsNews,
IsKids = request.IsKids,
IsSports = request.IsSports,
+ SortBy = request.GetOrderBy(),
+ SortOrder = request.SortOrder ?? SortOrder.Ascending,
AddCurrentProgram = request.AddCurrentProgram
}, CancellationToken.None).ConfigureAwait(false);
diff --git a/MediaBrowser.Api/Playback/BaseStreamingService.cs b/MediaBrowser.Api/Playback/BaseStreamingService.cs
index 8e57650b4a..fb4bd92445 100644
--- a/MediaBrowser.Api/Playback/BaseStreamingService.cs
+++ b/MediaBrowser.Api/Playback/BaseStreamingService.cs
@@ -2602,6 +2602,7 @@ namespace MediaBrowser.Api.Playback
inputModifier += " " + GetFastSeekCommandLineParameter(state.Request);
inputModifier = inputModifier.Trim();
+ //inputModifier += " -fflags +genpts+ignidx+igndts";
if (state.VideoRequest != null && genPts)
{
inputModifier += " -fflags +genpts";
diff --git a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
index d917b7d6d1..5e70cd5879 100644
--- a/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
+++ b/MediaBrowser.Controller/Entities/InternalItemsQuery.cs
@@ -151,6 +151,8 @@ namespace MediaBrowser.Controller.Entities
public Dictionary ExcludeProviderIds { get; set; }
public bool EnableGroupByMetadataKey { get; set; }
+ public List> OrderBy { get; set; }
+
public InternalItemsQuery()
{
GroupByPresentationUniqueKey = true;
@@ -193,6 +195,7 @@ namespace MediaBrowser.Controller.Entities
TrailerTypes = new TrailerType[] { };
AirDays = new DayOfWeek[] { };
SeriesStatuses = new SeriesStatus[] { };
+ OrderBy = new List>();
}
public InternalItemsQuery(User user)
diff --git a/MediaBrowser.Controller/LiveTv/LiveStream.cs b/MediaBrowser.Controller/LiveTv/LiveStream.cs
index 1bb1986327..7d44fbd909 100644
--- a/MediaBrowser.Controller/LiveTv/LiveStream.cs
+++ b/MediaBrowser.Controller/LiveTv/LiveStream.cs
@@ -13,11 +13,13 @@ namespace MediaBrowser.Controller.LiveTv
public int ConsumerCount { get; set; }
public ITunerHost TunerHost { get; set; }
public string OriginalStreamId { get; set; }
+ public bool EnableStreamSharing { get; set; }
public LiveStream(MediaSourceInfo mediaSource)
{
OriginalMediaSource = mediaSource;
OpenedMediaSource = mediaSource;
+ EnableStreamSharing = true;
}
public async Task Open(CancellationToken cancellationToken)
diff --git a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
index d3131eb5a8..44103e7206 100644
--- a/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
+++ b/MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs
@@ -235,6 +235,8 @@ namespace MediaBrowser.MediaEncoding.Encoder
throw new ResourceNotFoundException("ffprobe not found");
}
+ path = newPaths.Item1;
+
if (!ValidateVersion(path))
{
throw new ResourceNotFoundException("ffmpeg version 3.0 or greater is required.");
diff --git a/MediaBrowser.Model/Dlna/StreamInfo.cs b/MediaBrowser.Model/Dlna/StreamInfo.cs
index ac024f00b9..f7dc893c8c 100644
--- a/MediaBrowser.Model/Dlna/StreamInfo.cs
+++ b/MediaBrowser.Model/Dlna/StreamInfo.cs
@@ -215,13 +215,26 @@ namespace MediaBrowser.Model.Dlna
list.Add(new NameValuePair("MaxWidth", item.MaxWidth.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxWidth.Value) : string.Empty));
list.Add(new NameValuePair("MaxHeight", item.MaxHeight.HasValue ? StringHelper.ToStringCultureInvariant(item.MaxHeight.Value) : string.Empty));
- if (StringHelper.EqualsIgnoreCase(item.SubProtocol, "hls"))
+ var forceStartPosition = false;
+ long startPositionTicks = item.StartPositionTicks;
+ //if (item.MediaSource.DateLiveStreamOpened.HasValue && startPositionTicks == 0)
+ //{
+ // var elapsed = DateTime.UtcNow - item.MediaSource.DateLiveStreamOpened.Value;
+ // elapsed -= TimeSpan.FromSeconds(20);
+ // if (elapsed.TotalSeconds >= 0)
+ // {
+ // startPositionTicks = elapsed.Ticks + startPositionTicks;
+ // forceStartPosition = true;
+ // }
+ //}
+
+ if (StringHelper.EqualsIgnoreCase(item.SubProtocol, "hls") && !forceStartPosition)
{
list.Add(new NameValuePair("StartTimeTicks", string.Empty));
}
else
{
- list.Add(new NameValuePair("StartTimeTicks", StringHelper.ToStringCultureInvariant(item.StartPositionTicks)));
+ list.Add(new NameValuePair("StartTimeTicks", StringHelper.ToStringCultureInvariant(startPositionTicks)));
}
list.Add(new NameValuePair("Level", item.VideoLevel.HasValue ? StringHelper.ToStringCultureInvariant(item.VideoLevel.Value) : string.Empty));
diff --git a/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs b/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs
index f76368a7b1..4505b80a02 100644
--- a/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs
+++ b/MediaBrowser.Model/LiveTv/LiveTvChannelQuery.cs
@@ -1,4 +1,5 @@
-
+using MediaBrowser.Model.Entities;
+
namespace MediaBrowser.Model.LiveTv
{
///
@@ -85,9 +86,18 @@ namespace MediaBrowser.Model.LiveTv
public bool? IsSports { get; set; }
public bool? IsSeries { get; set; }
+ public string[] SortBy { get; set; }
+
+ ///
+ /// The sort order to return results with
+ ///
+ /// The sort order.
+ public SortOrder? SortOrder { get; set; }
+
public LiveTvChannelQuery()
{
EnableUserData = true;
+ SortBy = new string[] { };
}
}
}
diff --git a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs
index ee7dd8b985..a6240afe6d 100644
--- a/MediaBrowser.Model/LiveTv/LiveTvOptions.cs
+++ b/MediaBrowser.Model/LiveTv/LiveTvOptions.cs
@@ -60,7 +60,6 @@ namespace MediaBrowser.Model.LiveTv
public TunerHostInfo()
{
IsEnabled = true;
- AllowHWTranscoding = true;
}
}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index ef19dcbc91..3db764ae18 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -483,7 +483,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
if (existingTimer != null)
{
- if (existingTimer.Status == RecordingStatus.Cancelled)
+ if (existingTimer.Status == RecordingStatus.Cancelled ||
+ existingTimer.Status == RecordingStatus.Completed)
{
existingTimer.Status = RecordingStatus.New;
_timerProvider.Update(existingTimer);
@@ -832,12 +833,19 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
return result.Item2;
}
- private MediaSourceInfo CloneMediaSource(MediaSourceInfo mediaSource, int consumerId)
+ private MediaSourceInfo CloneMediaSource(MediaSourceInfo mediaSource, int consumerId, bool enableStreamSharing)
{
var json = _jsonSerializer.SerializeToString(mediaSource);
mediaSource = _jsonSerializer.DeserializeFromString(json);
- mediaSource.Id = consumerId.ToString(CultureInfo.InvariantCulture) + "_" + mediaSource.Id;
+ mediaSource.Id = Guid.NewGuid().ToString("N") + "_" + mediaSource.Id;
+
+ if (mediaSource.DateLiveStreamOpened.HasValue && enableStreamSharing)
+ {
+ var ticks = (DateTime.UtcNow - mediaSource.DateLiveStreamOpened.Value).Ticks - TimeSpan.FromSeconds(10).Ticks;
+ ticks = Math.Max(0, ticks);
+ mediaSource.Path += "?t=" + ticks.ToString(CultureInfo.InvariantCulture) + "&s=" + mediaSource.DateLiveStreamOpened.Value.Ticks.ToString(CultureInfo.InvariantCulture);
+ }
return mediaSource;
}
@@ -850,14 +858,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
var result = _liveStreams.Values.FirstOrDefault(i => string.Equals(i.OriginalStreamId, streamId, StringComparison.OrdinalIgnoreCase));
- if (result != null)
+ if (result != null && result.EnableStreamSharing)
{
- //result.ConsumerCount++;
+ result.ConsumerCount++;
- //_logger.Info("Live stream {0} consumer count is now {1}", streamId, result.ConsumerCount);
+ _logger.Info("Live stream {0} consumer count is now {1}", streamId, result.ConsumerCount);
- //_liveStreamsSemaphore.Release();
- //return new Tuple(result, CloneMediaSource(result.OpenedMediaSource, result.ConsumerCount - 1), result.TunerHost);
+ var openedMediaSource = CloneMediaSource(result.OpenedMediaSource, result.ConsumerCount - 1, result.EnableStreamSharing);
+ _liveStreamsSemaphore.Release();
+ return new Tuple(result, openedMediaSource, result.TunerHost);
}
try
@@ -868,16 +877,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{
result = await hostInstance.GetChannelStream(channelId, streamId, cancellationToken).ConfigureAwait(false);
- _liveStreams[result.OpenedMediaSource.Id] = result;
+ var openedMediaSource = CloneMediaSource(result.OpenedMediaSource, 0, result.EnableStreamSharing);
+
+ _liveStreams[openedMediaSource.Id] = result;
result.ConsumerCount++;
result.TunerHost = hostInstance;
result.OriginalStreamId = streamId;
_logger.Info("Returning mediasource streamId {0}, mediaSource.Id {1}, mediaSource.LiveStreamId {2}",
- streamId, result.OpenedMediaSource.Id, result.OpenedMediaSource.LiveStreamId);
+ streamId, openedMediaSource.Id, openedMediaSource.LiveStreamId);
- return new Tuple(result, CloneMediaSource(result.OpenedMediaSource, 0), hostInstance);
+ return new Tuple(result, openedMediaSource, hostInstance);
}
catch (FileNotFoundException)
{
@@ -925,7 +936,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
public async Task CloseLiveStream(string id, CancellationToken cancellationToken)
{
// Ignore the consumer id
- id = id.Substring(id.IndexOf('_') + 1);
+ //id = id.Substring(id.IndexOf('_') + 1);
await _liveStreamsSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
@@ -1143,8 +1154,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
try
{
- var allMediaSources =
- await GetChannelStreamMediaSources(timer.ChannelId, CancellationToken.None).ConfigureAwait(false);
+ var allMediaSources = await GetChannelStreamMediaSources(timer.ChannelId, CancellationToken.None).ConfigureAwait(false);
var liveStreamInfo = await GetChannelStreamInternal(timer.ChannelId, allMediaSources[0].Id, CancellationToken.None)
.ConfigureAwait(false);
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
index ce5f14f4b2..65e653551d 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
@@ -141,7 +141,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{
var maxBitrate = 25000000;
videoArgs = string.Format(
- "-codec:v:0 libx264 -force_key_frames \"expr:gte(t,n_forced*5)\" {0} -pix_fmt yuv420p -preset superfast -crf 23 -b:v {1} -maxrate {1} -bufsize ({1}*2) -vsync -1 -profile:v high -level 41",
+ "-codec:v:0 libx264 -force_key_frames \"expr:gte(t,n_forced*5)\" {0} -pix_fmt yuv420p -preset superfast -crf 23 -b:v {1} -maxrate {1} -bufsize ({1}*2) -vsync -1 -profile:v high -level 41 -tune zerolatency",
GetOutputSizeParam(),
maxBitrate.ToString(CultureInfo.InvariantCulture));
}
@@ -151,16 +151,33 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
}
var durationParam = " -t " + _mediaEncoder.GetTimeParameter(duration.Ticks);
- var commandLineArgs = "-fflags +genpts -async 1 -vsync -1 -i \"{0}\"{4} -sn {2} -map_metadata -1 -threads 0 {3} -y \"{1}\"";
+ var inputModifiers = "-fflags +genpts -async 1 -vsync -1";
+ var commandLineArgs = "-i \"{0}\"{4} -sn {2} -map_metadata -1 -threads 0 {3} -y \"{1}\"";
+
+ long startTimeTicks = 0;
+ //if (mediaSource.DateLiveStreamOpened.HasValue)
+ //{
+ // var elapsed = DateTime.UtcNow - mediaSource.DateLiveStreamOpened.Value;
+ // elapsed -= TimeSpan.FromSeconds(10);
+ // if (elapsed.TotalSeconds >= 0)
+ // {
+ // startTimeTicks = elapsed.Ticks + startTimeTicks;
+ // }
+ //}
if (mediaSource.ReadAtNativeFramerate)
{
- commandLineArgs = "-re " + commandLineArgs;
+ inputModifiers += " -re";
+ }
+
+ if (startTimeTicks > 0)
+ {
+ inputModifiers = "-ss " + _mediaEncoder.GetTimeParameter(startTimeTicks) + " " + inputModifiers;
}
commandLineArgs = string.Format(commandLineArgs, inputTempFile, targetFile, videoArgs, GetAudioArgs(mediaSource), durationParam);
- return commandLineArgs;
+ return inputModifiers + " " + commandLineArgs;
}
private string GetAudioArgs(MediaSourceInfo mediaSource)
diff --git a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
index 7c61d23965..f736307f05 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -148,7 +148,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var topFolder = await GetInternalLiveTvFolder(cancellationToken).ConfigureAwait(false);
- var channels = _libraryManager.GetItemList(new InternalItemsQuery
+ var internalQuery = new InternalItemsQuery(user)
{
IsMovie = query.IsMovie,
IsNews = query.IsNews,
@@ -156,109 +156,32 @@ namespace MediaBrowser.Server.Implementations.LiveTv
IsSports = query.IsSports,
IsSeries = query.IsSeries,
IncludeItemTypes = new[] { typeof(LiveTvChannel).Name },
- SortBy = new[] { ItemSortBy.SortName },
- TopParentIds = new[] { topFolder.Id.ToString("N") }
+ SortOrder = query.SortOrder ?? SortOrder.Ascending,
+ TopParentIds = new[] { topFolder.Id.ToString("N") },
+ IsFavorite = query.IsFavorite,
+ IsLiked = query.IsLiked,
+ StartIndex = query.StartIndex,
+ Limit = query.Limit
+ };
- }).Cast();
+ internalQuery.OrderBy.AddRange(query.SortBy.Select(i => new Tuple(i, query.SortOrder ?? SortOrder.Ascending)));
- if (user != null)
+ if (query.EnableFavoriteSorting)
{
- // Avoid implicitly captured closure
- var currentUser = user;
-
- channels = channels
- .Where(i => i.IsVisible(currentUser))
- .OrderBy(i =>
- {
- double number = 0;
-
- if (!string.IsNullOrEmpty(i.Number))
- {
- double.TryParse(i.Number, out number);
- }
-
- return number;
-
- });
-
- if (query.IsFavorite.HasValue)
- {
- var val = query.IsFavorite.Value;
-
- channels = channels
- .Where(i => _userDataManager.GetUserData(user, i).IsFavorite == val);
- }
-
- if (query.IsLiked.HasValue)
- {
- var val = query.IsLiked.Value;
-
- channels = channels
- .Where(i =>
- {
- var likes = _userDataManager.GetUserData(user, i).Likes;
-
- return likes.HasValue && likes.Value == val;
- });
- }
-
- if (query.IsDisliked.HasValue)
- {
- var val = query.IsDisliked.Value;
-
- channels = channels
- .Where(i =>
- {
- var likes = _userDataManager.GetUserData(user, i).Likes;
-
- return likes.HasValue && likes.Value != val;
- });
- }
+ internalQuery.OrderBy.Insert(0, new Tuple(ItemSortBy.IsFavoriteOrLiked, SortOrder.Descending));
}
- var enableFavoriteSorting = query.EnableFavoriteSorting;
-
- channels = channels.OrderBy(i =>
+ if (!internalQuery.OrderBy.Any(i => string.Equals(i.Item1, ItemSortBy.SortName, StringComparison.OrdinalIgnoreCase)))
{
- if (enableFavoriteSorting)
- {
- var userData = _userDataManager.GetUserData(user, i);
-
- if (userData.IsFavorite)
- {
- return 0;
- }
- if (userData.Likes.HasValue)
- {
- if (!userData.Likes.Value)
- {
- return 3;
- }
-
- return 1;
- }
- }
-
- return 2;
- });
-
- var allChannels = channels.ToList();
- IEnumerable allEnumerable = allChannels;
-
- if (query.StartIndex.HasValue)
- {
- allEnumerable = allEnumerable.Skip(query.StartIndex.Value);
+ internalQuery.OrderBy.Add(new Tuple(ItemSortBy.SortName, SortOrder.Ascending));
}
- if (query.Limit.HasValue)
- {
- allEnumerable = allEnumerable.Take(query.Limit.Value);
- }
+ var channelResult = _libraryManager.GetItemsResult(internalQuery);
var result = new QueryResult
{
- Items = allEnumerable.ToArray(),
- TotalRecordCount = allChannels.Count
+ Items = channelResult.Items.Cast().ToArray(),
+ TotalRecordCount = channelResult.TotalRecordCount
};
return result;
diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
index 68450105e2..14ae45228e 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
@@ -104,8 +104,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
});
}
+ private Dictionary _modelCache = new Dictionary();
private async Task GetModelInfo(TunerHostInfo info, CancellationToken cancellationToken)
{
+ lock (_modelCache)
+ {
+ DiscoverResponse response;
+ if (_modelCache.TryGetValue(info.Url, out response))
+ {
+ return response.ModelNumber;
+ }
+ }
+
try
{
using (var stream = await _httpClient.Get(new HttpRequestOptions()
@@ -119,6 +129,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{
var response = JsonSerializer.DeserializeFromStream(stream);
+ lock (_modelCache)
+ {
+ _modelCache[info.Id] = response;
+ }
+
return response.ModelNumber;
}
}
@@ -126,8 +141,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{
if (ex.StatusCode.HasValue && ex.StatusCode.Value == System.Net.HttpStatusCode.NotFound)
{
+ var defaultValue = "HDHR";
// HDHR4 doesn't have this api
- return "HDHR";
+ lock (_modelCache)
+ {
+ _modelCache[info.Id] = new DiscoverResponse
+ {
+ ModelNumber = defaultValue
+ };
+ }
+ return defaultValue;
}
throw;
@@ -427,18 +450,21 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
try
{
- string model = await GetModelInfo(info, cancellationToken).ConfigureAwait(false);
- model = model ?? string.Empty;
-
- if (info.AllowHWTranscoding && (model.IndexOf("hdtc", StringComparison.OrdinalIgnoreCase) != -1))
+ if (info.AllowHWTranscoding)
{
- list.Add(await GetMediaSource(info, hdhrId, "heavy").ConfigureAwait(false));
+ string model = await GetModelInfo(info, cancellationToken).ConfigureAwait(false);
+ model = model ?? string.Empty;
- list.Add(await GetMediaSource(info, hdhrId, "internet540").ConfigureAwait(false));
- list.Add(await GetMediaSource(info, hdhrId, "internet480").ConfigureAwait(false));
- list.Add(await GetMediaSource(info, hdhrId, "internet360").ConfigureAwait(false));
- list.Add(await GetMediaSource(info, hdhrId, "internet240").ConfigureAwait(false));
- list.Add(await GetMediaSource(info, hdhrId, "mobile").ConfigureAwait(false));
+ if ((model.IndexOf("hdtc", StringComparison.OrdinalIgnoreCase) != -1))
+ {
+ list.Add(await GetMediaSource(info, hdhrId, "heavy").ConfigureAwait(false));
+
+ list.Add(await GetMediaSource(info, hdhrId, "internet540").ConfigureAwait(false));
+ list.Add(await GetMediaSource(info, hdhrId, "internet480").ConfigureAwait(false));
+ list.Add(await GetMediaSource(info, hdhrId, "internet360").ConfigureAwait(false));
+ list.Add(await GetMediaSource(info, hdhrId, "internet240").ConfigureAwait(false));
+ list.Add(await GetMediaSource(info, hdhrId, "mobile").ConfigureAwait(false));
+ }
}
}
catch
@@ -474,6 +500,23 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
var mediaSource = await GetMediaSource(info, hdhrId, profile).ConfigureAwait(false);
var liveStream = new HdHomerunLiveStream(mediaSource, _fileSystem, _httpClient, Logger, Config.ApplicationPaths, _appHost);
+ if (info.AllowHWTranscoding)
+ {
+ var model = await GetModelInfo(info, cancellationToken).ConfigureAwait(false);
+
+ if ((model ?? string.Empty).IndexOf("hdtc", StringComparison.OrdinalIgnoreCase) != -1)
+ {
+ liveStream.EnableStreamSharing = !info.AllowHWTranscoding;
+ }
+ else
+ {
+ liveStream.EnableStreamSharing = true;
+ }
+ }
+ else
+ {
+ liveStream.EnableStreamSharing = true;
+ }
return liveStream;
}
@@ -484,6 +527,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
return;
}
+ lock (_modelCache)
+ {
+ _modelCache.Clear();
+ }
+
try
{
// Test it by pulling down the lineup
diff --git a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunLiveStream.cs b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunLiveStream.cs
index d6574db220..57722881db 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunLiveStream.cs
+++ b/MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunLiveStream.cs
@@ -52,11 +52,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
StartStreamingToTempFile(output, tempFile, url, taskCompletionSource, _liveStreamCancellationTokenSource.Token);
- await taskCompletionSource.Task.ConfigureAwait(false);
+ //OpenedMediaSource.Protocol = MediaProtocol.File;
+ //OpenedMediaSource.Path = tempFile;
+ //OpenedMediaSource.ReadAtNativeFramerate = true;
OpenedMediaSource.Path = _appHost.GetLocalApiUrl("localhost") + "/LiveTv/LiveStreamFiles/" + Path.GetFileNameWithoutExtension(tempFile) + "/stream.ts";
-
OpenedMediaSource.Protocol = MediaProtocol.Http;
+
+ await taskCompletionSource.Task.ConfigureAwait(false);
+
+ //await Task.Delay(5000).ConfigureAwait(false);
}
public override Task Close()
diff --git a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
index 097118418d..672cd1bc21 100644
--- a/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
+++ b/MediaBrowser.Server.Implementations/Persistence/SqliteItemRepository.cs
@@ -1730,28 +1730,28 @@ namespace MediaBrowser.Server.Implementations.Persistence
return true;
}
- if (query.SortBy != null && query.SortBy.Length > 0)
+ var sortingFields = query.SortBy.ToList();
+ sortingFields.AddRange(query.OrderBy.Select(i => i.Item1));
+
+ if (sortingFields.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase))
{
- if (query.SortBy.Contains(ItemSortBy.IsFavoriteOrLiked, StringComparer.OrdinalIgnoreCase))
- {
- return true;
- }
- if (query.SortBy.Contains(ItemSortBy.IsPlayed, StringComparer.OrdinalIgnoreCase))
- {
- return true;
- }
- if (query.SortBy.Contains(ItemSortBy.IsUnplayed, StringComparer.OrdinalIgnoreCase))
- {
- return true;
- }
- if (query.SortBy.Contains(ItemSortBy.PlayCount, StringComparer.OrdinalIgnoreCase))
- {
- return true;
- }
- if (query.SortBy.Contains(ItemSortBy.DatePlayed, StringComparer.OrdinalIgnoreCase))
- {
- return true;
- }
+ return true;
+ }
+ if (sortingFields.Contains(ItemSortBy.IsPlayed, StringComparer.OrdinalIgnoreCase))
+ {
+ return true;
+ }
+ if (sortingFields.Contains(ItemSortBy.IsUnplayed, StringComparer.OrdinalIgnoreCase))
+ {
+ return true;
+ }
+ if (sortingFields.Contains(ItemSortBy.PlayCount, StringComparer.OrdinalIgnoreCase))
+ {
+ return true;
+ }
+ if (sortingFields.Contains(ItemSortBy.DatePlayed, StringComparer.OrdinalIgnoreCase))
+ {
+ return true;
}
if (query.IsFavoriteOrLiked.HasValue)
@@ -2151,34 +2151,41 @@ namespace MediaBrowser.Server.Implementations.Persistence
private string GetOrderByText(InternalItemsQuery query)
{
+ var orderBy = query.OrderBy.ToList();
+ var enableOrderInversion = true;
+
+ if (orderBy.Count == 0)
+ {
+ orderBy.AddRange(query.SortBy.Select(i => new Tuple(i, query.SortOrder)));
+ }
+ else
+ {
+ enableOrderInversion = false;
+ }
+
if (query.SimilarTo != null)
{
- if (query.SortBy == null || query.SortBy.Length == 0)
+ if (orderBy.Count == 0)
{
- if (query.User != null)
- {
- query.SortBy = new[] { "SimilarityScore", ItemSortBy.Random };
- }
- else
- {
- query.SortBy = new[] { "SimilarityScore", ItemSortBy.Random };
- }
+ orderBy.Add(new Tuple("SimilarityScore", SortOrder.Descending));
+ orderBy.Add(new Tuple(ItemSortBy.Random, SortOrder.Ascending));
query.SortOrder = SortOrder.Descending;
+ enableOrderInversion = false;
}
}
- if (query.SortBy == null || query.SortBy.Length == 0)
+ query.OrderBy = orderBy;
+
+ if (orderBy.Count == 0)
{
return string.Empty;
}
- var isAscending = query.SortOrder != SortOrder.Descending;
-
- return " ORDER BY " + string.Join(",", query.SortBy.Select(i =>
+ return " ORDER BY " + string.Join(",", orderBy.Select(i =>
{
- var columnMap = MapOrderByField(i, query);
- var columnAscending = isAscending;
- if (columnMap.Item2)
+ var columnMap = MapOrderByField(i.Item1, query);
+ var columnAscending = i.Item2 == SortOrder.Ascending;
+ if (columnMap.Item2 && enableOrderInversion)
{
columnAscending = !columnAscending;
}