diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2016-10-29 18:22:20 -0400 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2016-10-29 18:22:20 -0400 |
| commit | dca78b13411db96366dddfa0d68bb6d36d28ad14 (patch) | |
| tree | 7d41e670f1cadec0db9e1ed7115e151da891f7ea /Emby.Dlna/Ssdp | |
| parent | 597e27d1c6199a40398abb068282711a9cb9db1b (diff) | |
rework dlna project
Diffstat (limited to 'Emby.Dlna/Ssdp')
| -rw-r--r-- | Emby.Dlna/Ssdp/DeviceDiscovery.cs | 141 | ||||
| -rw-r--r-- | Emby.Dlna/Ssdp/Extensions.cs | 34 |
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; + } + } +} |
