aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2016-03-17 15:29:53 -0400
committerLuke Pulverenti <luke.pulverenti@gmail.com>2016-03-17 15:29:53 -0400
commit623fd6ff92f3cddfbd617f7b9ac8734f611113c0 (patch)
tree6fb394d0e9c8264354f2bcdb8ee250e79914ba92
parent14b9f94e0a8516f96cc2e115ed767cb67260aa17 (diff)
update multi-tuner support
-rw-r--r--MediaBrowser.Dlna/Ssdp/SsdpHandler.cs4
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs5
-rw-r--r--MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs120
3 files changed, 97 insertions, 32 deletions
diff --git a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs b/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs
index 6205c5f70..dc271c557 100644
--- a/MediaBrowser.Dlna/Ssdp/SsdpHandler.cs
+++ b/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
+ }
}
}
diff --git a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index c88f88c6e..7e55d77d7 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/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);
diff --git a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
index 449943229..70638a8bd 100644
--- a/MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
+++ b/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)
{