update display of active recordings

This commit is contained in:
Luke Pulverenti
2016-10-11 02:46:59 -04:00
parent cb26cb9457
commit d5b5c8e1a5
33 changed files with 361 additions and 135 deletions

View File

@@ -598,7 +598,7 @@ namespace MediaBrowser.Server.Implementations.Dto
dto.Altitude = item.Altitude;
dto.IsoSpeedRating = item.IsoSpeedRating;
var album = item.Album;
var album = item.AlbumEntity;
if (album != null)
{

View File

@@ -269,9 +269,10 @@ namespace MediaBrowser.Server.Implementations.Library
positionTicks = 0;
}
if (item is Audio)
if (!item.SupportsPlayedStatus)
{
positionTicks = 0;
data.Played = false;
}
data.PlaybackPositionTicks = positionTicks;

View File

@@ -27,6 +27,7 @@ using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using CommonIO;
using MediaBrowser.Common.Events;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
@@ -59,8 +60,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
public static EmbyTV Current;
public event EventHandler DataSourceChanged { add { } remove { } }
public event EventHandler<RecordingStatusChangedEventArgs> RecordingStatusChanged { add { } remove { } }
public event EventHandler DataSourceChanged;
public event EventHandler<RecordingStatusChangedEventArgs> RecordingStatusChanged;
private readonly ConcurrentDictionary<string, ActiveRecordingInfo> _activeRecordings =
new ConcurrentDictionary<string, ActiveRecordingInfo>(StringComparer.OrdinalIgnoreCase);
@@ -1009,7 +1010,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
throw new NotImplementedException();
}
public Task<List<MediaSourceInfo>> GetRecordingStreamMediaSources(string recordingId, CancellationToken cancellationToken)
public async Task<List<MediaSourceInfo>> GetRecordingStreamMediaSources(string recordingId, CancellationToken cancellationToken)
{
ActiveRecordingInfo info;
@@ -1017,22 +1018,27 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
if (_activeRecordings.TryGetValue(recordingId, out info))
{
return Task.FromResult(new List<MediaSourceInfo>
var stream = new MediaSourceInfo
{
new MediaSourceInfo
{
Path = _appHost.GetLocalApiUrl("localhost") + "/LiveTv/LiveRecordings/" + recordingId + "/stream",
Id = recordingId,
SupportsDirectPlay = false,
SupportsDirectStream = true,
SupportsTranscoding = true,
IsInfiniteStream = true,
RequiresOpening = false,
RequiresClosing = false,
Protocol = Model.MediaInfo.MediaProtocol.Http,
BufferMs = 0
}
});
Path = _appHost.GetLocalApiUrl("localhost") + "/LiveTv/LiveRecordings/" + recordingId + "/stream",
Id = recordingId,
SupportsDirectPlay = false,
SupportsDirectStream = true,
SupportsTranscoding = true,
IsInfiniteStream = true,
RequiresOpening = false,
RequiresClosing = false,
Protocol = Model.MediaInfo.MediaProtocol.Http,
BufferMs = 0
};
var isAudio = false;
await new LiveStreamHelper(_mediaEncoder, _logger).AddMediaInfoWithProbe(stream, isAudio, cancellationToken).ConfigureAwait(false);
return new List<MediaSourceInfo>
{
stream
};
}
throw new FileNotFoundException();
@@ -1258,6 +1264,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
string liveStreamId = null;
OnRecordingStatusChanged();
try
{
var allMediaSources = await GetChannelStreamMediaSources(timer.ChannelId, CancellationToken.None).ConfigureAwait(false);
@@ -1353,6 +1361,16 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
{
_timerProvider.Delete(timer);
}
OnRecordingStatusChanged();
}
private void OnRecordingStatusChanged()
{
EventHelper.FireEventIfNotNull(RecordingStatusChanged, this, new RecordingStatusChangedEventArgs
{
}, _logger);
}
private async void EnforceKeepUpTo(TimerInfo timer)

View File

@@ -0,0 +1,110 @@
using System;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Logging;
namespace MediaBrowser.Server.Implementations.LiveTv
{
public class LiveStreamHelper
{
private readonly IMediaEncoder _mediaEncoder;
private readonly ILogger _logger;
public LiveStreamHelper(IMediaEncoder mediaEncoder, ILogger logger)
{
_mediaEncoder = mediaEncoder;
_logger = logger;
}
public async Task AddMediaInfoWithProbe(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken)
{
var originalRuntime = mediaSource.RunTimeTicks;
var now = DateTime.UtcNow;
var info = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest
{
InputPath = mediaSource.Path,
Protocol = mediaSource.Protocol,
MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video,
ExtractChapters = false,
AnalyzeDurationSections = 2
}, cancellationToken).ConfigureAwait(false);
_logger.Info("Live tv media info probe took {0} seconds", (DateTime.UtcNow - now).TotalSeconds.ToString(CultureInfo.InvariantCulture));
mediaSource.Bitrate = info.Bitrate;
mediaSource.Container = info.Container;
mediaSource.Formats = info.Formats;
mediaSource.MediaStreams = info.MediaStreams;
mediaSource.RunTimeTicks = info.RunTimeTicks;
mediaSource.Size = info.Size;
mediaSource.Timestamp = info.Timestamp;
mediaSource.Video3DFormat = info.Video3DFormat;
mediaSource.VideoType = info.VideoType;
mediaSource.DefaultSubtitleStreamIndex = null;
// Null this out so that it will be treated like a live stream
if (!originalRuntime.HasValue)
{
mediaSource.RunTimeTicks = null;
}
var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Audio);
if (audioStream == null || audioStream.Index == -1)
{
mediaSource.DefaultAudioStreamIndex = null;
}
else
{
mediaSource.DefaultAudioStreamIndex = audioStream.Index;
}
var videoStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Video);
if (videoStream != null)
{
if (!videoStream.BitRate.HasValue)
{
var width = videoStream.Width ?? 1920;
if (width >= 1900)
{
videoStream.BitRate = 8000000;
}
else if (width >= 1260)
{
videoStream.BitRate = 3000000;
}
else if (width >= 700)
{
videoStream.BitRate = 1000000;
}
}
// This is coming up false and preventing stream copy
videoStream.IsAVC = null;
}
// Try to estimate this
if (!mediaSource.Bitrate.HasValue)
{
var total = mediaSource.MediaStreams.Select(i => i.BitRate ?? 0).Sum();
if (total > 0)
{
mediaSource.Bitrate = total;
}
}
}
}
}

View File

@@ -121,9 +121,15 @@ namespace MediaBrowser.Server.Implementations.LiveTv
foreach (var service in _services)
{
service.DataSourceChanged += service_DataSourceChanged;
service.RecordingStatusChanged += Service_RecordingStatusChanged;
}
}
private void Service_RecordingStatusChanged(object sender, RecordingStatusChangedEventArgs e)
{
_lastRecordingRefreshTime = DateTime.MinValue;
}
public List<ITunerHost> TunerHosts
{
get { return _tunerHosts; }
@@ -2299,6 +2305,19 @@ namespace MediaBrowser.Server.Implementations.LiveTv
var info = await service.GetNewTimerDefaultsAsync(cancellationToken, programInfo).ConfigureAwait(false);
info.RecordAnyChannel = true;
info.RecordAnyTime = true;
info.Days = new List<DayOfWeek>
{
DayOfWeek.Sunday,
DayOfWeek.Monday,
DayOfWeek.Tuesday,
DayOfWeek.Wednesday,
DayOfWeek.Thursday,
DayOfWeek.Friday,
DayOfWeek.Saturday
};
info.Id = null;
return new Tuple<SeriesTimerInfo, ILiveTvService>(info, service);

View File

@@ -146,7 +146,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
}
else
{
await AddMediaInfoWithProbe(stream, isAudio, cancellationToken).ConfigureAwait(false);
await new LiveStreamHelper(_mediaEncoder, _logger).AddMediaInfoWithProbe(stream, isAudio, cancellationToken).ConfigureAwait(false);
}
}
catch (Exception ex)
@@ -216,92 +216,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv
}
}
private async Task AddMediaInfoWithProbe(MediaSourceInfo mediaSource, bool isAudio, CancellationToken cancellationToken)
{
var originalRuntime = mediaSource.RunTimeTicks;
var now = DateTime.UtcNow;
var info = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest
{
InputPath = mediaSource.Path,
Protocol = mediaSource.Protocol,
MediaType = isAudio ? DlnaProfileType.Audio : DlnaProfileType.Video,
ExtractChapters = false
}, cancellationToken).ConfigureAwait(false);
_logger.Info("Live tv media info probe took {0} seconds", (DateTime.UtcNow - now).TotalSeconds.ToString(CultureInfo.InvariantCulture));
mediaSource.Bitrate = info.Bitrate;
mediaSource.Container = info.Container;
mediaSource.Formats = info.Formats;
mediaSource.MediaStreams = info.MediaStreams;
mediaSource.RunTimeTicks = info.RunTimeTicks;
mediaSource.Size = info.Size;
mediaSource.Timestamp = info.Timestamp;
mediaSource.Video3DFormat = info.Video3DFormat;
mediaSource.VideoType = info.VideoType;
mediaSource.DefaultSubtitleStreamIndex = null;
// Null this out so that it will be treated like a live stream
if (!originalRuntime.HasValue)
{
mediaSource.RunTimeTicks = null;
}
var audioStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Audio);
if (audioStream == null || audioStream.Index == -1)
{
mediaSource.DefaultAudioStreamIndex = null;
}
else
{
mediaSource.DefaultAudioStreamIndex = audioStream.Index;
}
var videoStream = mediaSource.MediaStreams.FirstOrDefault(i => i.Type == Model.Entities.MediaStreamType.Video);
if (videoStream != null)
{
if (!videoStream.BitRate.HasValue)
{
var width = videoStream.Width ?? 1920;
if (width >= 1900)
{
videoStream.BitRate = 8000000;
}
else if (width >= 1260)
{
videoStream.BitRate = 3000000;
}
else if (width >= 700)
{
videoStream.BitRate = 1000000;
}
}
// This is coming up false and preventing stream copy
videoStream.IsAVC = null;
}
// Try to estimate this
if (!mediaSource.Bitrate.HasValue)
{
var total = mediaSource.MediaStreams.Select(i => i.BitRate ?? 0).Sum();
if (total > 0)
{
mediaSource.Bitrate = total;
}
}
}
public Task CloseMediaSource(string liveStreamId)
{
return _liveTvManager.CloseLiveStream(liveStreamId);

View File

@@ -234,6 +234,7 @@
<Compile Include="LiveTv\EmbyTV\TimerManager.cs" />
<Compile Include="LiveTv\Listings\SchedulesDirect.cs" />
<Compile Include="LiveTv\Listings\XmlTvListingsProvider.cs" />
<Compile Include="LiveTv\LiveStreamHelper.cs" />
<Compile Include="LiveTv\LiveTvConfigurationFactory.cs" />
<Compile Include="LiveTv\LiveTvDtoService.cs" />
<Compile Include="LiveTv\LiveTvManager.cs" />

View File

@@ -633,10 +633,14 @@ namespace MediaBrowser.Server.Implementations.Session
data.PlayCount++;
data.LastPlayedDate = DateTime.UtcNow;
if (!(item is Video))
if (!(item is Video) && item.SupportsPlayedStatus)
{
data.Played = true;
}
else
{
data.Played = false;
}
await _userDataManager.SaveUserData(userId, item, data, UserDataSaveReason.PlaybackStart, CancellationToken.None).ConfigureAwait(false);
}
@@ -847,11 +851,11 @@ namespace MediaBrowser.Server.Implementations.Session
{
playedToCompletion = _userDataManager.UpdatePlayState(item, data, positionTicks.Value);
}
else
else
{
// If the client isn't able to report this, then we'll just have to make an assumption
data.PlayCount++;
data.Played = true;
data.Played = item.SupportsPlayedStatus;
data.PlaybackPositionTicks = 0;
playedToCompletion = true;
}