|
@@ -1,5 +1,6 @@
|
|
|
using MediaBrowser.Common.Configuration;
|
|
|
using MediaBrowser.Controller.LiveTv;
|
|
|
+using MediaBrowser.Model.Dto;
|
|
|
using MediaBrowser.Model.LiveTv;
|
|
|
using MediaBrowser.Model.Logging;
|
|
|
using System;
|
|
@@ -83,11 +84,115 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
|
|
|
return list;
|
|
|
}
|
|
|
|
|
|
+ protected abstract Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken);
|
|
|
+
|
|
|
+ public async Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken)
|
|
|
+ {
|
|
|
+ if (IsValidChannelId(channelId))
|
|
|
+ {
|
|
|
+ var hosts = GetTunerHosts();
|
|
|
+
|
|
|
+ var hostsWithChannel = new List<TunerHostInfo>();
|
|
|
+
|
|
|
+ foreach (var host in hosts)
|
|
|
+ {
|
|
|
+ var channels = await GetChannels(host, true, cancellationToken).ConfigureAwait(false);
|
|
|
+
|
|
|
+ if (channels.Any(i => string.Equals(i.Id, channelId, StringComparison.OrdinalIgnoreCase)))
|
|
|
+ {
|
|
|
+ hostsWithChannel.Add(host);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (var host in hostsWithChannel)
|
|
|
+ {
|
|
|
+ // Check to make sure the tuner is available
|
|
|
+ // If there's only one tuner, don't bother with the check and just let the tuner be the one to throw an error
|
|
|
+ if (hostsWithChannel.Count > 1 && !await IsAvailable(host, channelId, cancellationToken).ConfigureAwait(false))
|
|
|
+ {
|
|
|
+ Logger.Error("Tuner is not currently available");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ var mediaSources = await GetChannelStreamMediaSources(host, channelId, cancellationToken).ConfigureAwait(false);
|
|
|
+
|
|
|
+ // Prefix the id with the host Id so that we can easily find it
|
|
|
+ foreach (var mediaSource in mediaSources)
|
|
|
+ {
|
|
|
+ mediaSource.Id = host.Id + mediaSource.Id;
|
|
|
+ }
|
|
|
+
|
|
|
+ return mediaSources;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return new List<MediaSourceInfo>();
|
|
|
+ }
|
|
|
+
|
|
|
+ protected abstract Task<MediaSourceInfo> GetChannelStream(TunerHostInfo tuner, string channelId, string streamId, CancellationToken cancellationToken);
|
|
|
+
|
|
|
+ public async Task<MediaSourceInfo> GetChannelStream(string channelId, string streamId, CancellationToken cancellationToken)
|
|
|
+ {
|
|
|
+ if (IsValidChannelId(channelId))
|
|
|
+ {
|
|
|
+ var hosts = GetTunerHosts();
|
|
|
+
|
|
|
+ var hostsWithChannel = new List<TunerHostInfo>();
|
|
|
+
|
|
|
+ foreach (var host in hosts)
|
|
|
+ {
|
|
|
+ if (string.IsNullOrWhiteSpace(streamId))
|
|
|
+ {
|
|
|
+ var channels = await GetChannels(host, true, cancellationToken).ConfigureAwait(false);
|
|
|
+
|
|
|
+ if (channels.Any(i => string.Equals(i.Id, channelId, StringComparison.OrdinalIgnoreCase)))
|
|
|
+ {
|
|
|
+ hostsWithChannel.Add(host);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else if (streamId.StartsWith(host.Id, StringComparison.OrdinalIgnoreCase))
|
|
|
+ {
|
|
|
+ hostsWithChannel = new List<TunerHostInfo> { host };
|
|
|
+ streamId = streamId.Substring(host.Id.Length);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (var host in hostsWithChannel)
|
|
|
+ {
|
|
|
+ // Check to make sure the tuner is available
|
|
|
+ // If there's only one tuner, don't bother with the check and just let the tuner be the one to throw an error
|
|
|
+ // If a streamId is specified then availibility has already been checked in GetChannelStreamMediaSources
|
|
|
+ if (string.IsNullOrWhiteSpace(streamId) && hostsWithChannel.Count > 1)
|
|
|
+ {
|
|
|
+ if (!await IsAvailable(host, channelId, cancellationToken).ConfigureAwait(false))
|
|
|
+ {
|
|
|
+ Logger.Error("Tuner is not currently available");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ var stream = await GetChannelStream(host, channelId, streamId, cancellationToken).ConfigureAwait(false);
|
|
|
+
|
|
|
+ if (stream != null)
|
|
|
+ {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ throw new LiveTvConflictException();
|
|
|
+ }
|
|
|
+
|
|
|
+ protected abstract Task<bool> IsAvailable(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken);
|
|
|
+
|
|
|
+ protected abstract bool IsValidChannelId(string channelId);
|
|
|
+
|
|
|
protected LiveTvOptions GetConfiguration()
|
|
|
{
|
|
|
return Config.GetConfiguration<LiveTvOptions>("livetv");
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
private class ChannelCache
|
|
|
{
|
|
|
public DateTime Date;
|