Explorar o código

update multi-tuner support

Luke Pulverenti %!s(int64=9) %!d(string=hai) anos
pai
achega
623fd6ff92

+ 4 - 0
MediaBrowser.Dlna/Ssdp/SsdpHandler.cs

@@ -588,6 +588,10 @@ namespace MediaBrowser.Dlna.Ssdp
                 {
 
                 }
+                catch (Exception)
+                {
+                    // If called while shutting down, seeing a NullReferenceException inside EndReceive
+                }
             }
         }
 

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

@@ -232,7 +232,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
                 }
             }
 
-            _channelCache = list;
+            _channelCache = list.ToList();
             return list;
         }
 
@@ -520,9 +520,12 @@ namespace MediaBrowser.Server.Implementations.LiveTv.EmbyTV
             {
                 if (!IsListingProviderEnabledForTuner(provider.Item2, channel.TunerHostId))
                 {
+                    _logger.Debug("Skipping getting programs for channel {0}-{1} from {2}-{3}, because it's not enabled for this tuner.", channel.Number, channel.Name, provider.Item1.Name, provider.Item2.ListingsId ?? string.Empty);
                     continue;
                 }
 
+                _logger.Debug("Getting programs for channel {0}-{1} from {2}-{3}", channel.Number, channel.Name, provider.Item1.Name, provider.Item2.ListingsId ?? string.Empty);
+                
                 var programs = await provider.Item1.GetProgramsAsync(provider.Item2, channel.Number, channel.Name, startDateUtc, endDateUtc, cancellationToken)
                         .ConfigureAwait(false);
 

+ 89 - 31
MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs

@@ -28,8 +28,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
 
         private const string ApiUrl = "https://json.schedulesdirect.org/20141201";
 
-        private readonly ConcurrentDictionary<string, ScheduleDirect.Station> _channelPair =
-            new ConcurrentDictionary<string, ScheduleDirect.Station>();
+        private readonly Dictionary<string, Dictionary<string, ScheduleDirect.Station>> _channelPairingCache =
+            new Dictionary<string, Dictionary<string, ScheduleDirect.Station>>(StringComparer.OrdinalIgnoreCase);
 
         public SchedulesDirect(ILogger logger, IJsonSerializer jsonSerializer, IHttpClient httpClient, IApplicationHost appHost)
         {
@@ -68,29 +68,19 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
 
             if (string.IsNullOrWhiteSpace(token))
             {
+                _logger.Warn("SchedulesDirect token is empty, returning empty program list");
                 return programsInfo;
             }
 
             if (string.IsNullOrWhiteSpace(info.ListingsId))
             {
+                _logger.Warn("ListingsId is null, returning empty program list");
                 return programsInfo;
             }
 
-            var httpOptions = new HttpRequestOptions()
-            {
-                Url = ApiUrl + "/schedules",
-                UserAgent = UserAgent,
-                CancellationToken = cancellationToken,
-                // The data can be large so give it some extra time
-                TimeoutMs = 60000,
-                LogErrorResponseBody = true
-            };
-
-            httpOptions.RequestHeaders["token"] = token;
-
             var dates = GetScheduleRequestDates(startDateUtc, endDateUtc);
 
-            ScheduleDirect.Station station = GetStation(channelNumber, channelName);
+            ScheduleDirect.Station station = GetStation(info.ListingsId, channelNumber, channelName);
 
             if (station == null)
             {
@@ -113,13 +103,26 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
 
             var requestString = _jsonSerializer.SerializeToString(requestList);
             _logger.Debug("Request string for schedules is: " + requestString);
+
+            var httpOptions = new HttpRequestOptions()
+            {
+                Url = ApiUrl + "/schedules",
+                UserAgent = UserAgent,
+                CancellationToken = cancellationToken,
+                // The data can be large so give it some extra time
+                TimeoutMs = 60000,
+                LogErrorResponseBody = true
+            };
+
+            httpOptions.RequestHeaders["token"] = token;
+
             httpOptions.RequestContent = requestString;
             using (var response = await Post(httpOptions, true, info).ConfigureAwait(false))
             {
                 StreamReader reader = new StreamReader(response.Content);
                 string responseString = reader.ReadToEnd();
                 var dailySchedules = _jsonSerializer.DeserializeFromString<List<ScheduleDirect.Day>>(responseString);
-                _logger.Debug("Found " + dailySchedules.Count() + " programs on " + channelNumber + " ScheduleDirect");
+                _logger.Debug("Found " + dailySchedules.Count + " programs on " + channelNumber + " ScheduleDirect");
 
                 httpOptions = new HttpRequestOptions()
                 {
@@ -176,23 +179,77 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
             return programsInfo;
         }
 
-        private ScheduleDirect.Station GetStation(string channelNumber, string channelName)
+        private readonly object _channelCacheLock = new object();
+        private ScheduleDirect.Station GetStation(string listingsId, string channelNumber, string channelName)
         {
-            ScheduleDirect.Station station;
+            lock (_channelCacheLock)
+            {
+                Dictionary<string, ScheduleDirect.Station> channelPair;
+                if (_channelPairingCache.TryGetValue(listingsId, out channelPair))
+                {
+                    ScheduleDirect.Station station;
+
+                    if (channelPair.TryGetValue(channelNumber, out station))
+                    {
+                        return station;
+                    }
 
-            if (_channelPair.TryGetValue(channelNumber, out station))
+                    if (string.IsNullOrWhiteSpace(channelName))
+                    {
+                        return null;
+                    }
+
+                    channelName = NormalizeName(channelName);
+
+                    return channelPair.Values.FirstOrDefault(i => string.Equals(NormalizeName(i.callsign ?? string.Empty), channelName, StringComparison.OrdinalIgnoreCase));
+                }
+
+                return null;
+            }
+        }
+
+        private void AddToChannelPairCache(string listingsId, string channelNumber, ScheduleDirect.Station schChannel)
+        {
+            lock (_channelCacheLock)
             {
-                return station;
+                Dictionary<string, ScheduleDirect.Station> cache;
+                if (_channelPairingCache.TryGetValue(listingsId, out cache))
+                {
+                    cache[channelNumber] = schChannel;
+                }
+                else
+                {
+                    cache = new Dictionary<string, ScheduleDirect.Station>();
+                    cache[channelNumber] = schChannel;
+                    _channelPairingCache[listingsId] = cache;
+                }
             }
+        }
 
-            if (string.IsNullOrWhiteSpace(channelName))
+        private void ClearPairCache(string listingsId)
+        {
+            lock (_channelCacheLock)
             {
-                return null;
+                Dictionary<string, ScheduleDirect.Station> cache;
+                if (_channelPairingCache.TryGetValue(listingsId, out cache))
+                {
+                    cache.Clear();
+                }
             }
+        }
 
-            channelName = NormalizeName(channelName);
+        private int GetChannelPairCacheCount(string listingsId)
+        {
+            lock (_channelCacheLock)
+            {
+                Dictionary<string, ScheduleDirect.Station> cache;
+                if (_channelPairingCache.TryGetValue(listingsId, out cache))
+                {
+                    return cache.Count;
+                }
 
-            return _channelPair.Values.FirstOrDefault(i => string.Equals(NormalizeName(i.callsign ?? string.Empty), channelName, StringComparison.OrdinalIgnoreCase));
+                return 0;
+            }
         }
 
         private string NormalizeName(string value)
@@ -203,7 +260,8 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
         public async Task AddMetadata(ListingsProviderInfo info, List<ChannelInfo> channels,
             CancellationToken cancellationToken)
         {
-            if (string.IsNullOrWhiteSpace(info.ListingsId))
+            var listingsId = info.ListingsId;
+            if (string.IsNullOrWhiteSpace(listingsId))
             {
                 throw new Exception("ListingsId required");
             }
@@ -215,11 +273,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
                 throw new Exception("token required");
             }
 
-            _channelPair.Clear();
+            ClearPairCache(listingsId);
 
             var httpOptions = new HttpRequestOptions()
             {
-                Url = ApiUrl + "/lineups/" + info.ListingsId,
+                Url = ApiUrl + "/lineups/" + listingsId,
                 UserAgent = UserAgent,
                 CancellationToken = cancellationToken,
                 LogErrorResponseBody = true,
@@ -232,7 +290,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
             using (var response = await Get(httpOptions, true, info).ConfigureAwait(false))
             {
                 var root = _jsonSerializer.DeserializeFromStream<ScheduleDirect.Channel>(response);
-                _logger.Info("Found " + root.map.Count() + " channels on the lineup on ScheduleDirect");
+                _logger.Info("Found " + root.map.Count + " channels on the lineup on ScheduleDirect");
                 _logger.Info("Mapping Stations to Channel");
                 foreach (ScheduleDirect.Map map in root.map)
                 {
@@ -251,13 +309,13 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
                     _logger.Debug("Found channel: " + channelNumber + " in Schedules Direct");
                     var schChannel = root.stations.FirstOrDefault(item => item.stationID == map.stationID);
 
-                    _channelPair.TryAdd(channelNumber, schChannel);
+                    AddToChannelPairCache(listingsId, channelNumber, schChannel);
                 }
-                _logger.Info("Added " + _channelPair.Count + " channels to the dictionary");
+                _logger.Info("Added " + GetChannelPairCacheCount(listingsId) + " channels to the dictionary");
 
                 foreach (ChannelInfo channel in channels)
                 {
-                    var station = GetStation(channel.Number, channel.Name);
+                    var station = GetStation(listingsId, channel.Number, channel.Name);
 
                     if (station != null)
                     {