aboutsummaryrefslogtreecommitdiff
path: root/Emby.Dlna/Ssdp
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2016-10-29 18:22:20 -0400
committerLuke Pulverenti <luke.pulverenti@gmail.com>2016-10-29 18:22:20 -0400
commitdca78b13411db96366dddfa0d68bb6d36d28ad14 (patch)
tree7d41e670f1cadec0db9e1ed7115e151da891f7ea /Emby.Dlna/Ssdp
parent597e27d1c6199a40398abb068282711a9cb9db1b (diff)
rework dlna project
Diffstat (limited to 'Emby.Dlna/Ssdp')
-rw-r--r--Emby.Dlna/Ssdp/DeviceDiscovery.cs141
-rw-r--r--Emby.Dlna/Ssdp/Extensions.cs34
2 files changed, 175 insertions, 0 deletions
diff --git a/Emby.Dlna/Ssdp/DeviceDiscovery.cs b/Emby.Dlna/Ssdp/DeviceDiscovery.cs
new file mode 100644
index 0000000000..56b6c8e5c6
--- /dev/null
+++ b/Emby.Dlna/Ssdp/DeviceDiscovery.cs
@@ -0,0 +1,141 @@
+using MediaBrowser.Common.Events;
+using MediaBrowser.Controller;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Dlna;
+using MediaBrowser.Model.Logging;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Model.Dlna;
+using MediaBrowser.Model.Events;
+using Rssdp;
+
+namespace MediaBrowser.Dlna.Ssdp
+{
+ public class DeviceDiscovery : IDeviceDiscovery, IDisposable
+ {
+ private bool _disposed;
+
+ private readonly ILogger _logger;
+ private readonly IServerConfigurationManager _config;
+ private readonly CancellationTokenSource _tokenSource;
+
+ public event EventHandler<GenericEventArgs<UpnpDeviceInfo>> DeviceDiscovered;
+ public event EventHandler<GenericEventArgs<UpnpDeviceInfo>> DeviceLeft;
+
+ private SsdpDeviceLocator _DeviceLocator;
+
+ public DeviceDiscovery(ILogger logger, IServerConfigurationManager config)
+ {
+ _tokenSource = new CancellationTokenSource();
+
+ _logger = logger;
+ _config = config;
+ }
+
+ // Call this method from somewhere in your code to start the search.
+ public void BeginSearch()
+ {
+ _DeviceLocator = new SsdpDeviceLocator();
+
+ // (Optional) Set the filter so we only see notifications for devices we care about
+ // (can be any search target value i.e device type, uuid value etc - any value that appears in the
+ // DiscoverdSsdpDevice.NotificationType property or that is used with the searchTarget parameter of the Search method).
+ //_DeviceLocator.NotificationFilter = "upnp:rootdevice";
+
+ // Connect our event handler so we process devices as they are found
+ _DeviceLocator.DeviceAvailable += deviceLocator_DeviceAvailable;
+ _DeviceLocator.DeviceUnavailable += _DeviceLocator_DeviceUnavailable;
+
+ // Perform a search so we don't have to wait for devices to broadcast notifications
+ // again to get any results right away (notifications are broadcast periodically).
+ StartAsyncSearch();
+ }
+
+ private void StartAsyncSearch()
+ {
+ Task.Factory.StartNew(async (o) =>
+ {
+ while (!_tokenSource.IsCancellationRequested)
+ {
+ try
+ {
+ // Enable listening for notifications (optional)
+ _DeviceLocator.StartListeningForNotifications();
+
+ await _DeviceLocator.SearchAsync().ConfigureAwait(false);
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error searching for devices", ex);
+ }
+
+ var delay = _config.GetDlnaConfiguration().ClientDiscoveryIntervalSeconds * 1000;
+
+ await Task.Delay(delay, _tokenSource.Token).ConfigureAwait(false);
+ }
+
+ }, CancellationToken.None, TaskCreationOptions.LongRunning);
+ }
+
+ // Process each found device in the event handler
+ void deviceLocator_DeviceAvailable(object sender, DeviceAvailableEventArgs e)
+ {
+ var originalHeaders = e.DiscoveredDevice.ResponseHeaders;
+
+ var headerDict = originalHeaders == null ? new Dictionary<string, KeyValuePair<string, IEnumerable<string>>>() : originalHeaders.ToDictionary(i => i.Key, StringComparer.OrdinalIgnoreCase);
+
+ var headers = headerDict.ToDictionary(i => i.Key, i => i.Value.Value.FirstOrDefault(), StringComparer.OrdinalIgnoreCase);
+
+ var args = new GenericEventArgs<UpnpDeviceInfo>
+ {
+ Argument = new UpnpDeviceInfo
+ {
+ Location = e.DiscoveredDevice.DescriptionLocation,
+ Headers = headers
+ }
+ };
+
+ EventHelper.FireEventIfNotNull(DeviceDiscovered, this, args, _logger);
+ }
+
+ private void _DeviceLocator_DeviceUnavailable(object sender, DeviceUnavailableEventArgs e)
+ {
+ var originalHeaders = e.DiscoveredDevice.ResponseHeaders;
+
+ var headerDict = originalHeaders == null ? new Dictionary<string, KeyValuePair<string, IEnumerable<string>>>() : originalHeaders.ToDictionary(i => i.Key, StringComparer.OrdinalIgnoreCase);
+
+ var headers = headerDict.ToDictionary(i => i.Key, i => i.Value.Value.FirstOrDefault(), StringComparer.OrdinalIgnoreCase);
+
+ var args = new GenericEventArgs<UpnpDeviceInfo>
+ {
+ Argument = new UpnpDeviceInfo
+ {
+ Location = e.DiscoveredDevice.DescriptionLocation,
+ Headers = headers
+ }
+ };
+
+ EventHelper.FireEventIfNotNull(DeviceLeft, this, args, _logger);
+ }
+
+ public void Start()
+ {
+ BeginSearch();
+ }
+
+ public void Dispose()
+ {
+ if (!_disposed)
+ {
+ _disposed = true;
+ _tokenSource.Cancel();
+ }
+ }
+ }
+}
diff --git a/Emby.Dlna/Ssdp/Extensions.cs b/Emby.Dlna/Ssdp/Extensions.cs
new file mode 100644
index 0000000000..17ebcc7ead
--- /dev/null
+++ b/Emby.Dlna/Ssdp/Extensions.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading.Tasks;
+using System.Xml.Linq;
+
+namespace MediaBrowser.Dlna.Ssdp
+{
+ public static class Extensions
+ {
+ public static string GetValue(this XElement container, XName name)
+ {
+ var node = container.Element(name);
+
+ return node == null ? null : node.Value;
+ }
+
+ public static string GetAttributeValue(this XElement container, XName name)
+ {
+ var node = container.Attribute(name);
+
+ return node == null ? null : node.Value;
+ }
+
+ public static string GetDescendantValue(this XElement container, XName name)
+ {
+ var node = container.Descendants(name)
+ .FirstOrDefault();
+
+ return node == null ? null : node.Value;
+ }
+ }
+}