|
|
@ -227,10 +227,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|
|
|
|
|
|
|
|
|
|
|
public async Task<MediaSourceInfo> GetRecordingStream(string id, CancellationToken cancellationToken)
|
|
|
|
public async Task<MediaSourceInfo> GetRecordingStream(string id, CancellationToken cancellationToken)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return await GetLiveStream(id, null, false, cancellationToken).ConfigureAwait(false);
|
|
|
|
var info = await GetLiveStream(id, null, false, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return info.Item1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public async Task<MediaSourceInfo> GetChannelStream(string id, string mediaSourceId, CancellationToken cancellationToken)
|
|
|
|
public async Task<Tuple<MediaSourceInfo, IDirectStreamProvider>> GetChannelStream(string id, string mediaSourceId, CancellationToken cancellationToken)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
return await GetLiveStream(id, mediaSourceId, true, cancellationToken).ConfigureAwait(false);
|
|
|
|
return await GetLiveStream(id, mediaSourceId, true, cancellationToken).ConfigureAwait(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -280,7 +282,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|
|
|
return _services.FirstOrDefault(i => string.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase));
|
|
|
|
return _services.FirstOrDefault(i => string.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private async Task<MediaSourceInfo> GetLiveStream(string id, string mediaSourceId, bool isChannel, CancellationToken cancellationToken)
|
|
|
|
private async Task<Tuple<MediaSourceInfo, IDirectStreamProvider>> GetLiveStream(string id, string mediaSourceId, bool isChannel, CancellationToken cancellationToken)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
|
|
|
await _liveStreamSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
|
|
|
|
|
|
|
|
|
|
|
@ -294,6 +296,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|
|
|
MediaSourceInfo info;
|
|
|
|
MediaSourceInfo info;
|
|
|
|
bool isVideo;
|
|
|
|
bool isVideo;
|
|
|
|
ILiveTvService service;
|
|
|
|
ILiveTvService service;
|
|
|
|
|
|
|
|
IDirectStreamProvider directStreamProvider = null;
|
|
|
|
|
|
|
|
|
|
|
|
if (isChannel)
|
|
|
|
if (isChannel)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -301,7 +304,18 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|
|
|
isVideo = channel.ChannelType == ChannelType.TV;
|
|
|
|
isVideo = channel.ChannelType == ChannelType.TV;
|
|
|
|
service = GetService(channel);
|
|
|
|
service = GetService(channel);
|
|
|
|
_logger.Info("Opening channel stream from {0}, external channel Id: {1}", service.Name, channel.ExternalId);
|
|
|
|
_logger.Info("Opening channel stream from {0}, external channel Id: {1}", service.Name, channel.ExternalId);
|
|
|
|
info = await service.GetChannelStream(channel.ExternalId, mediaSourceId, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
|
|
|
|
|
|
|
var supportsManagedStream = service as ISupportsDirectStreamProvider;
|
|
|
|
|
|
|
|
if (supportsManagedStream != null)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
var streamInfo = await supportsManagedStream.GetChannelStreamWithDirectStreamProvider(channel.ExternalId, mediaSourceId, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
|
|
|
info = streamInfo.Item1;
|
|
|
|
|
|
|
|
directStreamProvider = streamInfo.Item2;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
info = await service.GetChannelStream(channel.ExternalId, mediaSourceId, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
|
|
|
}
|
|
|
|
info.RequiresClosing = true;
|
|
|
|
info.RequiresClosing = true;
|
|
|
|
|
|
|
|
|
|
|
|
if (info.RequiresClosing)
|
|
|
|
if (info.RequiresClosing)
|
|
|
@ -332,7 +346,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|
|
|
_logger.Info("Live stream info: {0}", _jsonSerializer.SerializeToString(info));
|
|
|
|
_logger.Info("Live stream info: {0}", _jsonSerializer.SerializeToString(info));
|
|
|
|
Normalize(info, service, isVideo);
|
|
|
|
Normalize(info, service, isVideo);
|
|
|
|
|
|
|
|
|
|
|
|
return info;
|
|
|
|
return new Tuple<MediaSourceInfo, IDirectStreamProvider>(info, directStreamProvider);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (Exception ex)
|
|
|
|
catch (Exception ex)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -544,11 +558,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|
|
|
return item;
|
|
|
|
return item;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private async Task<LiveTvProgram> GetProgram(ProgramInfo info, LiveTvChannel channel, ChannelType channelType, string serviceName, CancellationToken cancellationToken)
|
|
|
|
private async Task<LiveTvProgram> GetProgram(ProgramInfo info, Dictionary<Guid, LiveTvProgram> allExistingPrograms, LiveTvChannel channel, ChannelType channelType, string serviceName, CancellationToken cancellationToken)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var id = _tvDtoService.GetInternalProgramId(serviceName, info.Id);
|
|
|
|
var id = _tvDtoService.GetInternalProgramId(serviceName, info.Id);
|
|
|
|
|
|
|
|
|
|
|
|
var item = _libraryManager.GetItemById(id) as LiveTvProgram;
|
|
|
|
LiveTvProgram item = null;
|
|
|
|
|
|
|
|
allExistingPrograms.TryGetValue(id, out item);
|
|
|
|
|
|
|
|
|
|
|
|
var isNew = false;
|
|
|
|
var isNew = false;
|
|
|
|
var forceUpdate = false;
|
|
|
|
var forceUpdate = false;
|
|
|
|
|
|
|
|
|
|
|
@ -877,7 +893,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|
|
|
|
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(query.SeriesTimerId))
|
|
|
|
if (!string.IsNullOrWhiteSpace(query.SeriesTimerId))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var seriesTimers = await GetSeriesTimersInternal(new SeriesTimerQuery {}, cancellationToken).ConfigureAwait(false);
|
|
|
|
var seriesTimers = await GetSeriesTimersInternal(new SeriesTimerQuery { }, cancellationToken).ConfigureAwait(false);
|
|
|
|
var seriesTimer = seriesTimers.Items.FirstOrDefault(i => string.Equals(_tvDtoService.GetInternalSeriesTimerId(i.ServiceName, i.Id).ToString("N"), query.SeriesTimerId, StringComparison.OrdinalIgnoreCase));
|
|
|
|
var seriesTimer = seriesTimers.Items.FirstOrDefault(i => string.Equals(_tvDtoService.GetInternalSeriesTimerId(i.ServiceName, i.Id).ToString("N"), query.SeriesTimerId, StringComparison.OrdinalIgnoreCase));
|
|
|
|
if (seriesTimer != null)
|
|
|
|
if (seriesTimer != null)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -1265,9 +1281,17 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|
|
|
|
|
|
|
|
|
|
|
var channelPrograms = await service.GetProgramsAsync(currentChannel.ExternalId, start, end, cancellationToken).ConfigureAwait(false);
|
|
|
|
var channelPrograms = await service.GetProgramsAsync(currentChannel.ExternalId, start, end, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var existingPrograms = _libraryManager.GetItemList(new InternalItemsQuery
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
IncludeItemTypes = new string[] { typeof(LiveTvProgram).Name },
|
|
|
|
|
|
|
|
ChannelIds = new string[] { currentChannel.Id.ToString("N") }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}).Cast<LiveTvProgram>().ToDictionary(i => i.Id);
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var program in channelPrograms)
|
|
|
|
foreach (var program in channelPrograms)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
var programItem = await GetProgram(program, currentChannel, currentChannel.ChannelType, service.Name, cancellationToken).ConfigureAwait(false);
|
|
|
|
var programItem = await GetProgram(program, existingPrograms, currentChannel, currentChannel.ChannelType, service.Name, cancellationToken).ConfigureAwait(false);
|
|
|
|
|
|
|
|
|
|
|
|
programs.Add(programItem.Id);
|
|
|
|
programs.Add(programItem.Id);
|
|
|
|
|
|
|
|
|
|
|
@ -1881,11 +1905,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (query.IsScheduled.Value)
|
|
|
|
if (query.IsScheduled.Value)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
timers = timers.Where(i => i.Item1.Status == RecordingStatus.New || i.Item1.Status == RecordingStatus.Scheduled);
|
|
|
|
timers = timers.Where(i => i.Item1.Status == RecordingStatus.New);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
else
|
|
|
|
{
|
|
|
|
{
|
|
|
|
timers = timers.Where(i => !(i.Item1.Status == RecordingStatus.New || i.Item1.Status == RecordingStatus.Scheduled));
|
|
|
|
timers = timers.Where(i => !(i.Item1.Status == RecordingStatus.New));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|