2
0
Luke Pulverenti 9 жил өмнө
parent
commit
8c32aefb53

+ 2 - 4
MediaBrowser.Controller/LiveTv/ITunerHost.cs

@@ -33,20 +33,18 @@ namespace MediaBrowser.Controller.LiveTv
         /// <summary>
         /// Gets the channel stream.
         /// </summary>
-        /// <param name="info">The information.</param>
         /// <param name="channelId">The channel identifier.</param>
         /// <param name="streamId">The stream identifier.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task&lt;MediaSourceInfo&gt;.</returns>
-        Task<MediaSourceInfo> GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken);
+        Task<MediaSourceInfo> GetChannelStream(string channelId, string streamId, CancellationToken cancellationToken);
         /// <summary>
         /// Gets the channel stream media sources.
         /// </summary>
-        /// <param name="info">The information.</param>
         /// <param name="channelId">The channel identifier.</param>
         /// <param name="cancellationToken">The cancellation token.</param>
         /// <returns>Task&lt;List&lt;MediaSourceInfo&gt;&gt;.</returns>
-        Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(TunerHostInfo info, string channelId, CancellationToken cancellationToken);
+        Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken);
         /// <summary>
         /// Validates the specified information.
         /// </summary>

+ 4 - 35
MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs

@@ -1,6 +1,5 @@
 using MediaBrowser.Common;
 using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.IO;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Drawing;
@@ -13,7 +12,6 @@ using MediaBrowser.Model.Serialization;
 using System;
 using System.Collections.Concurrent;
 using System.Collections.Generic;
-using System.Globalization;
 using System.IO;
 using System.Linq;
 using System.Threading;
@@ -161,20 +159,6 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
             return GetChannelsAsync(false, cancellationToken);
         }
 
-        private List<Tuple<ITunerHost, TunerHostInfo>> GetTunerHosts()
-        {
-            return GetConfiguration().TunerHosts
-                .Where(i => i.IsEnabled)
-                .Select(i =>
-                {
-                    var provider = _liveTvManager.TunerHosts.FirstOrDefault(l => string.Equals(l.Type, i.Type, StringComparison.OrdinalIgnoreCase));
-
-                    return provider == null ? null : new Tuple<ITunerHost, TunerHostInfo>(provider, i);
-                })
-                .Where(i => i != null)
-                .ToList();
-        }
-
         public Task CancelSeriesTimerAsync(string timerId, CancellationToken cancellationToken)
         {
             var timers = _timerProvider.GetAll().Where(i => string.Equals(i.SeriesTimerId, timerId, StringComparison.OrdinalIgnoreCase));
@@ -409,22 +393,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
         {
             _logger.Info("Streaming Channel " + channelId);
 
-            foreach (var hostInstance in GetTunerHosts())
+            foreach (var hostInstance in _liveTvManager.TunerHosts)
             {
-                if (!string.IsNullOrWhiteSpace(streamId))
-                {
-                    var originalStreamId = string.Join("-", streamId.Split('-').Skip(1).ToArray());
-
-                    if (!string.Equals(hostInstance.Item2.Id, originalStreamId, StringComparison.OrdinalIgnoreCase))
-                    {
-                        continue;
-                    }
-                }
-
                 MediaSourceInfo mediaSourceInfo = null;
                 try
                 {
-                    mediaSourceInfo = await hostInstance.Item1.GetChannelStream(hostInstance.Item2, channelId, streamId, cancellationToken).ConfigureAwait(false);
+                    mediaSourceInfo = await hostInstance.GetChannelStream(channelId, streamId, cancellationToken).ConfigureAwait(false);
                 }
                 catch (Exception e)
                 {
@@ -443,16 +417,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
 
         public async Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(string channelId, CancellationToken cancellationToken)
         {
-            foreach (var hostInstance in GetTunerHosts())
+            foreach (var hostInstance in _liveTvManager.TunerHosts)
             {
                 try
                 {
-                    var sources = await hostInstance.Item1.GetChannelStreamMediaSources(hostInstance.Item2, channelId, cancellationToken).ConfigureAwait(false);
-
-                    foreach (var source in sources)
-                    {
-                        source.Id = hostInstance.Item2.Id + "-" + source.Id;
-                    }
+                    var sources = await hostInstance.GetChannelStreamMediaSources(channelId, cancellationToken).ConfigureAwait(false);
 
                     if (sources.Count > 0)
                     {

+ 106 - 1
MediaBrowser.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs

@@ -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;

+ 13 - 2
MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs

@@ -329,7 +329,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
             return mediaSource;
         }
 
-        public async Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(TunerHostInfo info, string channelId, CancellationToken cancellationToken)
+        protected override async Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(TunerHostInfo info, string channelId, CancellationToken cancellationToken)
         {
             var list = new List<MediaSourceInfo>();
 
@@ -364,7 +364,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
             return list;
         }
 
-        public async Task<MediaSourceInfo> GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken)
+        protected override bool IsValidChannelId(string channelId)
+        {
+            return channelId.StartsWith(ChannelIdPrefix, StringComparison.OrdinalIgnoreCase);
+        }
+
+        protected override async Task<MediaSourceInfo> GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken)
         {
             if (!channelId.StartsWith(ChannelIdPrefix, StringComparison.OrdinalIgnoreCase))
             {
@@ -379,5 +384,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
         {
             await GetChannels(info, false, CancellationToken.None).ConfigureAwait(false);
         }
+
+        protected override async Task<bool> IsAvailable(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken)
+        {
+            // TODO
+            return true;
+        }
     }
 }

+ 21 - 7
MediaBrowser.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs

@@ -17,7 +17,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
 {
     public class M3UTunerHost : BaseTunerHost, ITunerHost
     {
-        public M3UTunerHost(IConfigurationManager config, ILogger logger) : base(config, logger)
+        public M3UTunerHost(IConfigurationManager config, ILogger logger)
+            : base(config, logger)
         {
         }
 
@@ -31,6 +32,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
             get { return "M3U Tuner"; }
         }
 
+        private const string ChannelIdPrefix = "m3u_";
+
         protected override async Task<IEnumerable<ChannelInfo>> GetChannelsInternal(TunerHostInfo info, CancellationToken cancellationToken)
         {
             var url = info.Url;
@@ -88,7 +91,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
                             switch (list[0])
                             {
                                 case "tvg-id":
-                                    channels.Last().Id = urlHash + list[1];
+                                    channels.Last().Id = ChannelIdPrefix + urlHash + list[1];
                                     channels.Last().Number = list[1];
                                     break;
                                 case "tvg-name":
@@ -117,19 +120,20 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
                 Url = i.Url
             })
             .ToList();
-            
+
             return Task.FromResult(list);
         }
 
-        public async Task<MediaSourceInfo> GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken)
+        protected override async Task<MediaSourceInfo> GetChannelStream(TunerHostInfo info, string channelId, string streamId, CancellationToken cancellationToken)
         {
             var urlHash = info.Url.GetMD5().ToString("N");
-            if (!channelId.StartsWith(urlHash, StringComparison.OrdinalIgnoreCase))
+            var prefix = ChannelIdPrefix + urlHash;
+            if (!channelId.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
             {
                 return null;
             }
 
-            channelId = channelId.Substring(urlHash.Length);
+            channelId = channelId.Substring(prefix.Length);
 
             var channels = await GetChannels(info, true, cancellationToken).ConfigureAwait(false);
             var m3uchannels = channels.Cast<M3UChannel>();
@@ -196,9 +200,19 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
             }
         }
 
-        public Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(TunerHostInfo info, string channelId, CancellationToken cancellationToken)
+        protected override bool IsValidChannelId(string channelId)
+        {
+            return channelId.StartsWith(ChannelIdPrefix, StringComparison.OrdinalIgnoreCase);
+        }
+
+        protected override Task<List<MediaSourceInfo>> GetChannelStreamMediaSources(TunerHostInfo info, string channelId, CancellationToken cancellationToken)
         {
             throw new NotImplementedException();
         }
+
+        protected override Task<bool> IsAvailable(TunerHostInfo tuner, string channelId, CancellationToken cancellationToken)
+        {
+            return Task.FromResult(true);
+        }
     }
 }