|
@@ -21,225 +21,225 @@ using MediaBrowser.Model.Serialization;
|
|
|
|
|
|
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp
|
|
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.SatIp
|
|
{
|
|
{
|
|
- public class SatIpDiscovery : IServerEntryPoint
|
|
|
|
- {
|
|
|
|
- private readonly IDeviceDiscovery _deviceDiscovery;
|
|
|
|
- private readonly IServerConfigurationManager _config;
|
|
|
|
- private readonly ILogger _logger;
|
|
|
|
- private readonly ILiveTvManager _liveTvManager;
|
|
|
|
- private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
|
|
|
|
- private readonly IHttpClient _httpClient;
|
|
|
|
- private readonly IJsonSerializer _json;
|
|
|
|
-
|
|
|
|
- public static SatIpDiscovery Current;
|
|
|
|
-
|
|
|
|
- private readonly List<TunerHostInfo> _discoveredHosts = new List<TunerHostInfo>();
|
|
|
|
-
|
|
|
|
- public List<TunerHostInfo> DiscoveredHosts
|
|
|
|
- {
|
|
|
|
- get { return _discoveredHosts.ToList(); }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public SatIpDiscovery(IDeviceDiscovery deviceDiscovery, IServerConfigurationManager config, ILogger logger, ILiveTvManager liveTvManager, IHttpClient httpClient, IJsonSerializer json)
|
|
|
|
- {
|
|
|
|
- _deviceDiscovery = deviceDiscovery;
|
|
|
|
- _config = config;
|
|
|
|
- _logger = logger;
|
|
|
|
- _liveTvManager = liveTvManager;
|
|
|
|
- _httpClient = httpClient;
|
|
|
|
- _json = json;
|
|
|
|
- Current = this;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public void Run()
|
|
|
|
- {
|
|
|
|
- _deviceDiscovery.DeviceDiscovered += _deviceDiscovery_DeviceDiscovered;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- void _deviceDiscovery_DeviceDiscovered(object sender, SsdpMessageEventArgs e)
|
|
|
|
- {
|
|
|
|
- string st = null;
|
|
|
|
- string nt = null;
|
|
|
|
- e.Headers.TryGetValue("ST", out st);
|
|
|
|
- e.Headers.TryGetValue("NT", out nt);
|
|
|
|
-
|
|
|
|
- if (string.Equals(st, "urn:ses-com:device:SatIPServer:1", StringComparison.OrdinalIgnoreCase) ||
|
|
|
|
- string.Equals(nt, "urn:ses-com:device:SatIPServer:1", StringComparison.OrdinalIgnoreCase))
|
|
|
|
- {
|
|
|
|
- string location;
|
|
|
|
- if (e.Headers.TryGetValue("Location", out location) && !string.IsNullOrWhiteSpace(location))
|
|
|
|
- {
|
|
|
|
- _logger.Debug("SAT IP found at {0}", location);
|
|
|
|
-
|
|
|
|
- // Just get the beginning of the url
|
|
|
|
- AddDevice(location);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private async void AddDevice(string location)
|
|
|
|
- {
|
|
|
|
- await _semaphore.WaitAsync().ConfigureAwait(false);
|
|
|
|
-
|
|
|
|
- try
|
|
|
|
- {
|
|
|
|
- if (_discoveredHosts.Any(i => string.Equals(i.Type, SatIpHost.DeviceType, StringComparison.OrdinalIgnoreCase) && string.Equals(location, i.Url, StringComparison.OrdinalIgnoreCase)))
|
|
|
|
- {
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- _logger.Debug("Will attempt to add SAT device {0}", location);
|
|
|
|
- var info = await GetInfo(location, CancellationToken.None).ConfigureAwait(false);
|
|
|
|
-
|
|
|
|
- _discoveredHosts.Add(info);
|
|
|
|
- }
|
|
|
|
- catch (OperationCanceledException)
|
|
|
|
- {
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
- catch (NotImplementedException)
|
|
|
|
- {
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
- catch (Exception ex)
|
|
|
|
- {
|
|
|
|
- _logger.ErrorException("Error saving device", ex);
|
|
|
|
- }
|
|
|
|
- finally
|
|
|
|
- {
|
|
|
|
- _semaphore.Release();
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public void Dispose()
|
|
|
|
- {
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- public async Task<SatIpTunerHostInfo> GetInfo(string url, CancellationToken cancellationToken)
|
|
|
|
- {
|
|
|
|
- var result = new SatIpTunerHostInfo
|
|
|
|
- {
|
|
|
|
- Url = url,
|
|
|
|
- IsEnabled = true,
|
|
|
|
- Type = SatIpHost.DeviceType,
|
|
|
|
- Tuners = 1,
|
|
|
|
- TunersAvailable = 1
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- using (var stream = await _httpClient.Get(url, cancellationToken).ConfigureAwait(false))
|
|
|
|
- {
|
|
|
|
- using (var streamReader = new StreamReader(stream))
|
|
|
|
- {
|
|
|
|
- // Use XmlReader for best performance
|
|
|
|
- using (var reader = XmlReader.Create(streamReader))
|
|
|
|
- {
|
|
|
|
- reader.MoveToContent();
|
|
|
|
-
|
|
|
|
- // Loop through each element
|
|
|
|
- while (reader.Read())
|
|
|
|
- {
|
|
|
|
- if (reader.NodeType == XmlNodeType.Element)
|
|
|
|
- {
|
|
|
|
- switch (reader.Name)
|
|
|
|
- {
|
|
|
|
- case "device":
|
|
|
|
- using (var subtree = reader.ReadSubtree())
|
|
|
|
- {
|
|
|
|
- FillFromDeviceNode(result, subtree);
|
|
|
|
- }
|
|
|
|
- break;
|
|
|
|
- default:
|
|
|
|
- reader.Skip();
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (string.IsNullOrWhiteSpace(result.Id))
|
|
|
|
- {
|
|
|
|
- throw new NotImplementedException();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // Device hasn't implemented an m3u list
|
|
|
|
- if (string.IsNullOrWhiteSpace(result.M3UUrl))
|
|
|
|
- {
|
|
|
|
- result.IsEnabled = false;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- else if (!result.M3UUrl.StartsWith("http", StringComparison.OrdinalIgnoreCase))
|
|
|
|
- {
|
|
|
|
- var fullM3uUrl = url.Substring(0, url.LastIndexOf('/'));
|
|
|
|
- result.M3UUrl = fullM3uUrl + "/" + result.M3UUrl.TrimStart('/');
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- _logger.Debug("SAT device result: {0}", _json.SerializeToString(result));
|
|
|
|
-
|
|
|
|
- return result;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- private void FillFromDeviceNode(SatIpTunerHostInfo info, XmlReader reader)
|
|
|
|
- {
|
|
|
|
- reader.MoveToContent();
|
|
|
|
-
|
|
|
|
- while (reader.Read())
|
|
|
|
- {
|
|
|
|
- if (reader.NodeType == XmlNodeType.Element)
|
|
|
|
- {
|
|
|
|
- switch (reader.LocalName)
|
|
|
|
- {
|
|
|
|
- case "UDN":
|
|
|
|
- {
|
|
|
|
- info.Id = reader.ReadElementContentAsString();
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- case "friendlyName":
|
|
|
|
- {
|
|
|
|
- info.FriendlyName = reader.ReadElementContentAsString();
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- case "satip:X_SATIPCAP":
|
|
|
|
- case "X_SATIPCAP":
|
|
|
|
- {
|
|
|
|
- // <satip:X_SATIPCAP xmlns:satip="urn:ses-com:satip">DVBS2-2</satip:X_SATIPCAP>
|
|
|
|
- var value = reader.ReadElementContentAsString() ?? string.Empty;
|
|
|
|
- var parts = value.Split(new[] { '-' }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
- if (parts.Length == 2)
|
|
|
|
- {
|
|
|
|
- int intValue;
|
|
|
|
- if (int.TryParse(parts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out intValue))
|
|
|
|
- {
|
|
|
|
- info.TunersAvailable = intValue;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (int.TryParse(parts[0].Substring(parts[0].Length - 1), NumberStyles.Any, CultureInfo.InvariantCulture, out intValue))
|
|
|
|
- {
|
|
|
|
- info.Tuners = intValue;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- case "satip:X_SATIPM3U":
|
|
|
|
- case "X_SATIPM3U":
|
|
|
|
- {
|
|
|
|
- // <satip:X_SATIPM3U xmlns:satip="urn:ses-com:satip">/channellist.lua?select=m3u</satip:X_SATIPM3U>
|
|
|
|
- info.M3UUrl = reader.ReadElementContentAsString();
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- default:
|
|
|
|
- reader.Skip();
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ //public class SatIpDiscovery : IServerEntryPoint
|
|
|
|
+ //{
|
|
|
|
+ // private readonly IDeviceDiscovery _deviceDiscovery;
|
|
|
|
+ // private readonly IServerConfigurationManager _config;
|
|
|
|
+ // private readonly ILogger _logger;
|
|
|
|
+ // private readonly ILiveTvManager _liveTvManager;
|
|
|
|
+ // private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
|
|
|
|
+ // private readonly IHttpClient _httpClient;
|
|
|
|
+ // private readonly IJsonSerializer _json;
|
|
|
|
+
|
|
|
|
+ // public static SatIpDiscovery Current;
|
|
|
|
+
|
|
|
|
+ // private readonly List<TunerHostInfo> _discoveredHosts = new List<TunerHostInfo>();
|
|
|
|
+
|
|
|
|
+ // public List<TunerHostInfo> DiscoveredHosts
|
|
|
|
+ // {
|
|
|
|
+ // get { return _discoveredHosts.ToList(); }
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // public SatIpDiscovery(IDeviceDiscovery deviceDiscovery, IServerConfigurationManager config, ILogger logger, ILiveTvManager liveTvManager, IHttpClient httpClient, IJsonSerializer json)
|
|
|
|
+ // {
|
|
|
|
+ // _deviceDiscovery = deviceDiscovery;
|
|
|
|
+ // _config = config;
|
|
|
|
+ // _logger = logger;
|
|
|
|
+ // _liveTvManager = liveTvManager;
|
|
|
|
+ // _httpClient = httpClient;
|
|
|
|
+ // _json = json;
|
|
|
|
+ // Current = this;
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // public void Run()
|
|
|
|
+ // {
|
|
|
|
+ // _deviceDiscovery.DeviceDiscovered += _deviceDiscovery_DeviceDiscovered;
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // void _deviceDiscovery_DeviceDiscovered(object sender, SsdpMessageEventArgs e)
|
|
|
|
+ // {
|
|
|
|
+ // string st = null;
|
|
|
|
+ // string nt = null;
|
|
|
|
+ // e.Headers.TryGetValue("ST", out st);
|
|
|
|
+ // e.Headers.TryGetValue("NT", out nt);
|
|
|
|
+
|
|
|
|
+ // if (string.Equals(st, "urn:ses-com:device:SatIPServer:1", StringComparison.OrdinalIgnoreCase) ||
|
|
|
|
+ // string.Equals(nt, "urn:ses-com:device:SatIPServer:1", StringComparison.OrdinalIgnoreCase))
|
|
|
|
+ // {
|
|
|
|
+ // string location;
|
|
|
|
+ // if (e.Headers.TryGetValue("Location", out location) && !string.IsNullOrWhiteSpace(location))
|
|
|
|
+ // {
|
|
|
|
+ // _logger.Debug("SAT IP found at {0}", location);
|
|
|
|
+
|
|
|
|
+ // // Just get the beginning of the url
|
|
|
|
+ // AddDevice(location);
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // private async void AddDevice(string location)
|
|
|
|
+ // {
|
|
|
|
+ // await _semaphore.WaitAsync().ConfigureAwait(false);
|
|
|
|
+
|
|
|
|
+ // try
|
|
|
|
+ // {
|
|
|
|
+ // if (_discoveredHosts.Any(i => string.Equals(i.Type, SatIpHost.DeviceType, StringComparison.OrdinalIgnoreCase) && string.Equals(location, i.Url, StringComparison.OrdinalIgnoreCase)))
|
|
|
|
+ // {
|
|
|
|
+ // return;
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // _logger.Debug("Will attempt to add SAT device {0}", location);
|
|
|
|
+ // var info = await GetInfo(location, CancellationToken.None).ConfigureAwait(false);
|
|
|
|
+
|
|
|
|
+ // _discoveredHosts.Add(info);
|
|
|
|
+ // }
|
|
|
|
+ // catch (OperationCanceledException)
|
|
|
|
+ // {
|
|
|
|
+
|
|
|
|
+ // }
|
|
|
|
+ // catch (NotImplementedException)
|
|
|
|
+ // {
|
|
|
|
+
|
|
|
|
+ // }
|
|
|
|
+ // catch (Exception ex)
|
|
|
|
+ // {
|
|
|
|
+ // _logger.ErrorException("Error saving device", ex);
|
|
|
|
+ // }
|
|
|
|
+ // finally
|
|
|
|
+ // {
|
|
|
|
+ // _semaphore.Release();
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // public void Dispose()
|
|
|
|
+ // {
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // public async Task<SatIpTunerHostInfo> GetInfo(string url, CancellationToken cancellationToken)
|
|
|
|
+ // {
|
|
|
|
+ // var result = new SatIpTunerHostInfo
|
|
|
|
+ // {
|
|
|
|
+ // Url = url,
|
|
|
|
+ // IsEnabled = true,
|
|
|
|
+ // Type = SatIpHost.DeviceType,
|
|
|
|
+ // Tuners = 1,
|
|
|
|
+ // TunersAvailable = 1
|
|
|
|
+ // };
|
|
|
|
+
|
|
|
|
+ // using (var stream = await _httpClient.Get(url, cancellationToken).ConfigureAwait(false))
|
|
|
|
+ // {
|
|
|
|
+ // using (var streamReader = new StreamReader(stream))
|
|
|
|
+ // {
|
|
|
|
+ // // Use XmlReader for best performance
|
|
|
|
+ // using (var reader = XmlReader.Create(streamReader))
|
|
|
|
+ // {
|
|
|
|
+ // reader.MoveToContent();
|
|
|
|
+
|
|
|
|
+ // // Loop through each element
|
|
|
|
+ // while (reader.Read())
|
|
|
|
+ // {
|
|
|
|
+ // if (reader.NodeType == XmlNodeType.Element)
|
|
|
|
+ // {
|
|
|
|
+ // switch (reader.Name)
|
|
|
|
+ // {
|
|
|
|
+ // case "device":
|
|
|
|
+ // using (var subtree = reader.ReadSubtree())
|
|
|
|
+ // {
|
|
|
|
+ // FillFromDeviceNode(result, subtree);
|
|
|
|
+ // }
|
|
|
|
+ // break;
|
|
|
|
+ // default:
|
|
|
|
+ // reader.Skip();
|
|
|
|
+ // break;
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // if (string.IsNullOrWhiteSpace(result.Id))
|
|
|
|
+ // {
|
|
|
|
+ // throw new NotImplementedException();
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // // Device hasn't implemented an m3u list
|
|
|
|
+ // if (string.IsNullOrWhiteSpace(result.M3UUrl))
|
|
|
|
+ // {
|
|
|
|
+ // result.IsEnabled = false;
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // else if (!result.M3UUrl.StartsWith("http", StringComparison.OrdinalIgnoreCase))
|
|
|
|
+ // {
|
|
|
|
+ // var fullM3uUrl = url.Substring(0, url.LastIndexOf('/'));
|
|
|
|
+ // result.M3UUrl = fullM3uUrl + "/" + result.M3UUrl.TrimStart('/');
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // _logger.Debug("SAT device result: {0}", _json.SerializeToString(result));
|
|
|
|
+
|
|
|
|
+ // return result;
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // private void FillFromDeviceNode(SatIpTunerHostInfo info, XmlReader reader)
|
|
|
|
+ // {
|
|
|
|
+ // reader.MoveToContent();
|
|
|
|
+
|
|
|
|
+ // while (reader.Read())
|
|
|
|
+ // {
|
|
|
|
+ // if (reader.NodeType == XmlNodeType.Element)
|
|
|
|
+ // {
|
|
|
|
+ // switch (reader.LocalName)
|
|
|
|
+ // {
|
|
|
|
+ // case "UDN":
|
|
|
|
+ // {
|
|
|
|
+ // info.Id = reader.ReadElementContentAsString();
|
|
|
|
+ // break;
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // case "friendlyName":
|
|
|
|
+ // {
|
|
|
|
+ // info.FriendlyName = reader.ReadElementContentAsString();
|
|
|
|
+ // break;
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // case "satip:X_SATIPCAP":
|
|
|
|
+ // case "X_SATIPCAP":
|
|
|
|
+ // {
|
|
|
|
+ // // <satip:X_SATIPCAP xmlns:satip="urn:ses-com:satip">DVBS2-2</satip:X_SATIPCAP>
|
|
|
|
+ // var value = reader.ReadElementContentAsString() ?? string.Empty;
|
|
|
|
+ // var parts = value.Split(new[] { '-' }, StringSplitOptions.RemoveEmptyEntries);
|
|
|
|
+ // if (parts.Length == 2)
|
|
|
|
+ // {
|
|
|
|
+ // int intValue;
|
|
|
|
+ // if (int.TryParse(parts[1], NumberStyles.Any, CultureInfo.InvariantCulture, out intValue))
|
|
|
|
+ // {
|
|
|
|
+ // info.TunersAvailable = intValue;
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // if (int.TryParse(parts[0].Substring(parts[0].Length - 1), NumberStyles.Any, CultureInfo.InvariantCulture, out intValue))
|
|
|
|
+ // {
|
|
|
|
+ // info.Tuners = intValue;
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+ // break;
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // case "satip:X_SATIPM3U":
|
|
|
|
+ // case "X_SATIPM3U":
|
|
|
|
+ // {
|
|
|
|
+ // // <satip:X_SATIPM3U xmlns:satip="urn:ses-com:satip">/channellist.lua?select=m3u</satip:X_SATIPM3U>
|
|
|
|
+ // info.M3UUrl = reader.ReadElementContentAsString();
|
|
|
|
+ // break;
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ // default:
|
|
|
|
+ // reader.Skip();
|
|
|
|
+ // break;
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+ // }
|
|
|
|
+ //}
|
|
|
|
|
|
public class SatIpTunerHostInfo : TunerHostInfo
|
|
public class SatIpTunerHostInfo : TunerHostInfo
|
|
{
|
|
{
|