add hdhomerun auto-discovery

pull/702/head
Luke Pulverenti 9 years ago
parent 23bab40308
commit ffd9460d51

@ -0,0 +1,10 @@
using System;
namespace MediaBrowser.Controller.Dlna
{
public interface IDeviceDiscovery
{
event EventHandler<SsdpMessageEventArgs> DeviceDiscovered;
event EventHandler<SsdpMessageEventArgs> DeviceLeft;
}
}

@ -113,6 +113,7 @@
<Compile Include="Dlna\EventSubscriptionResponse.cs" /> <Compile Include="Dlna\EventSubscriptionResponse.cs" />
<Compile Include="Dlna\IConnectionManager.cs" /> <Compile Include="Dlna\IConnectionManager.cs" />
<Compile Include="Dlna\IContentDirectory.cs" /> <Compile Include="Dlna\IContentDirectory.cs" />
<Compile Include="Dlna\IDeviceDiscovery.cs" />
<Compile Include="Dlna\IDlnaManager.cs" /> <Compile Include="Dlna\IDlnaManager.cs" />
<Compile Include="Dlna\IEventManager.cs" /> <Compile Include="Dlna\IEventManager.cs" />
<Compile Include="Dlna\IMediaReceiverRegistrar.cs" /> <Compile Include="Dlna\IMediaReceiverRegistrar.cs" />

@ -24,7 +24,7 @@ namespace MediaBrowser.Dlna.Channels
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IHttpClient _httpClient; private readonly IHttpClient _httpClient;
private DeviceDiscovery _deviceDiscovery; private readonly IDeviceDiscovery _deviceDiscovery;
private readonly SemaphoreSlim _syncLock = new SemaphoreSlim(1, 1); private readonly SemaphoreSlim _syncLock = new SemaphoreSlim(1, 1);
private List<Device> _servers = new List<Device>(); private List<Device> _servers = new List<Device>();
@ -33,21 +33,21 @@ namespace MediaBrowser.Dlna.Channels
private Func<List<string>> _localServersLookup; private Func<List<string>> _localServersLookup;
public DlnaChannelFactory(IServerConfigurationManager config, IHttpClient httpClient, ILogger logger) public DlnaChannelFactory(IServerConfigurationManager config, IHttpClient httpClient, ILogger logger, IDeviceDiscovery deviceDiscovery)
{ {
_config = config; _config = config;
_httpClient = httpClient; _httpClient = httpClient;
_logger = logger; _logger = logger;
_deviceDiscovery = deviceDiscovery;
Instance = this; Instance = this;
} }
internal void Start(DeviceDiscovery deviceDiscovery, Func<List<string>> localServersLookup) internal void Start(Func<List<string>> localServersLookup)
{ {
_localServersLookup = localServersLookup; _localServersLookup = localServersLookup;
_deviceDiscovery = deviceDiscovery;
//deviceDiscovery.DeviceDiscovered += deviceDiscovery_DeviceDiscovered; //deviceDiscovery.DeviceDiscovered += deviceDiscovery_DeviceDiscovered;
deviceDiscovery.DeviceLeft += deviceDiscovery_DeviceLeft; _deviceDiscovery.DeviceLeft += deviceDiscovery_DeviceLeft;
} }
async void deviceDiscovery_DeviceDiscovered(object sender, SsdpMessageEventArgs e) async void deviceDiscovery_DeviceDiscovered(object sender, SsdpMessageEventArgs e)

@ -38,7 +38,7 @@ namespace MediaBrowser.Dlna.Main
private readonly IMediaSourceManager _mediaSourceManager; private readonly IMediaSourceManager _mediaSourceManager;
private readonly SsdpHandler _ssdpHandler; private readonly SsdpHandler _ssdpHandler;
private DeviceDiscovery _deviceDiscovery; private readonly IDeviceDiscovery _deviceDiscovery;
private readonly List<string> _registeredServerIds = new List<string>(); private readonly List<string> _registeredServerIds = new List<string>();
private bool _dlnaServerStarted; private bool _dlnaServerStarted;
@ -56,7 +56,7 @@ namespace MediaBrowser.Dlna.Main
IUserDataManager userDataManager, IUserDataManager userDataManager,
ILocalizationManager localization, ILocalizationManager localization,
IMediaSourceManager mediaSourceManager, IMediaSourceManager mediaSourceManager,
ISsdpHandler ssdpHandler) ISsdpHandler ssdpHandler, IDeviceDiscovery deviceDiscovery)
{ {
_config = config; _config = config;
_appHost = appHost; _appHost = appHost;
@ -70,6 +70,7 @@ namespace MediaBrowser.Dlna.Main
_userDataManager = userDataManager; _userDataManager = userDataManager;
_localization = localization; _localization = localization;
_mediaSourceManager = mediaSourceManager; _mediaSourceManager = mediaSourceManager;
_deviceDiscovery = deviceDiscovery;
_ssdpHandler = (SsdpHandler)ssdpHandler; _ssdpHandler = (SsdpHandler)ssdpHandler;
_logger = logManager.GetLogger("Dlna"); _logger = logManager.GetLogger("Dlna");
} }
@ -81,7 +82,7 @@ namespace MediaBrowser.Dlna.Main
_config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated; _config.NamedConfigurationUpdated += _config_NamedConfigurationUpdated;
DlnaChannelFactory.Instance.Start(_deviceDiscovery, () => _registeredServerIds); DlnaChannelFactory.Instance.Start(() => _registeredServerIds);
} }
void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e) void _config_NamedConfigurationUpdated(object sender, ConfigurationUpdateEventArgs e)
@ -125,9 +126,7 @@ namespace MediaBrowser.Dlna.Main
{ {
_ssdpHandler.Start(); _ssdpHandler.Start();
_deviceDiscovery = new DeviceDiscovery(_logger, _config, _ssdpHandler, _appHost); ((DeviceDiscovery)_deviceDiscovery).Start(_ssdpHandler);
_deviceDiscovery.Start();
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -135,18 +134,6 @@ namespace MediaBrowser.Dlna.Main
} }
} }
private void DisposeDeviceDiscovery()
{
try
{
_deviceDiscovery.Dispose();
}
catch (Exception ex)
{
_logger.ErrorException("Error disposing device discovery", ex);
}
}
public void StartDlnaServer() public void StartDlnaServer()
{ {
try try
@ -240,7 +227,6 @@ namespace MediaBrowser.Dlna.Main
{ {
DisposeDlnaServer(); DisposeDlnaServer();
DisposePlayToManager(); DisposePlayToManager();
DisposeDeviceDiscovery();
} }
public void DisposeDlnaServer() public void DisposeDlnaServer()

@ -5,7 +5,6 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Localization; using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Session; using MediaBrowser.Controller.Session;
using MediaBrowser.Dlna.Didl; using MediaBrowser.Dlna.Didl;
using MediaBrowser.Dlna.Ssdp;
using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Dto; using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities; using MediaBrowser.Model.Entities;
@ -35,7 +34,7 @@ namespace MediaBrowser.Dlna.PlayTo
private readonly ILocalizationManager _localization; private readonly ILocalizationManager _localization;
private readonly IMediaSourceManager _mediaSourceManager; private readonly IMediaSourceManager _mediaSourceManager;
private readonly DeviceDiscovery _deviceDiscovery; private readonly IDeviceDiscovery _deviceDiscovery;
private readonly string _serverAddress; private readonly string _serverAddress;
private readonly string _accessToken; private readonly string _accessToken;
@ -58,7 +57,7 @@ namespace MediaBrowser.Dlna.PlayTo
private Timer _updateTimer; private Timer _updateTimer;
public PlayToController(SessionInfo session, ISessionManager sessionManager, ILibraryManager libraryManager, ILogger logger, IDlnaManager dlnaManager, IUserManager userManager, IImageProcessor imageProcessor, string serverAddress, string accessToken, DeviceDiscovery deviceDiscovery, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager) public PlayToController(SessionInfo session, ISessionManager sessionManager, ILibraryManager libraryManager, ILogger logger, IDlnaManager dlnaManager, IUserManager userManager, IImageProcessor imageProcessor, string serverAddress, string accessToken, IDeviceDiscovery deviceDiscovery, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager)
{ {
_session = session; _session = session;
_sessionManager = sessionManager; _sessionManager = sessionManager;

@ -32,13 +32,13 @@ namespace MediaBrowser.Dlna.PlayTo
private readonly IUserDataManager _userDataManager; private readonly IUserDataManager _userDataManager;
private readonly ILocalizationManager _localization; private readonly ILocalizationManager _localization;
private readonly DeviceDiscovery _deviceDiscovery; private readonly IDeviceDiscovery _deviceDiscovery;
private readonly IMediaSourceManager _mediaSourceManager; private readonly IMediaSourceManager _mediaSourceManager;
private readonly List<string> _nonRendererUrls = new List<string>(); private readonly List<string> _nonRendererUrls = new List<string>();
private Timer _clearNonRenderersTimer; private Timer _clearNonRenderersTimer;
public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, DeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager) public PlayToManager(ILogger logger, ISessionManager sessionManager, ILibraryManager libraryManager, IUserManager userManager, IDlnaManager dlnaManager, IServerApplicationHost appHost, IImageProcessor imageProcessor, IDeviceDiscovery deviceDiscovery, IHttpClient httpClient, IServerConfigurationManager config, IUserDataManager userDataManager, ILocalizationManager localization, IMediaSourceManager mediaSourceManager)
{ {
_logger = logger; _logger = logger;
_sessionManager = sessionManager; _sessionManager = sessionManager;

@ -14,31 +14,31 @@ using System.Threading.Tasks;
namespace MediaBrowser.Dlna.Ssdp namespace MediaBrowser.Dlna.Ssdp
{ {
public class DeviceDiscovery : IDisposable public class DeviceDiscovery : IDeviceDiscovery, IDisposable
{ {
private bool _disposed; private bool _disposed;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IServerConfigurationManager _config; private readonly IServerConfigurationManager _config;
private readonly SsdpHandler _ssdpHandler; private SsdpHandler _ssdpHandler;
private readonly CancellationTokenSource _tokenSource; private readonly CancellationTokenSource _tokenSource;
private readonly IServerApplicationHost _appHost; private readonly IServerApplicationHost _appHost;
public event EventHandler<SsdpMessageEventArgs> DeviceDiscovered; public event EventHandler<SsdpMessageEventArgs> DeviceDiscovered;
public event EventHandler<SsdpMessageEventArgs> DeviceLeft; public event EventHandler<SsdpMessageEventArgs> DeviceLeft;
public DeviceDiscovery(ILogger logger, IServerConfigurationManager config, SsdpHandler ssdpHandler, IServerApplicationHost appHost) public DeviceDiscovery(ILogger logger, IServerConfigurationManager config, IServerApplicationHost appHost)
{ {
_tokenSource = new CancellationTokenSource(); _tokenSource = new CancellationTokenSource();
_logger = logger; _logger = logger;
_config = config; _config = config;
_ssdpHandler = ssdpHandler;
_appHost = appHost; _appHost = appHost;
} }
public void Start() public void Start(SsdpHandler ssdpHandler)
{ {
_ssdpHandler = ssdpHandler;
_ssdpHandler.MessageReceived += _ssdpHandler_MessageReceived; _ssdpHandler.MessageReceived += _ssdpHandler_MessageReceived;
foreach (var network in GetNetworkInterfaces()) foreach (var network in GetNetworkInterfaces())
@ -71,7 +71,7 @@ namespace MediaBrowser.Dlna.Ssdp
} }
} }
} }
void _ssdpHandler_MessageReceived(object sender, SsdpMessageEventArgs e) void _ssdpHandler_MessageReceived(object sender, SsdpMessageEventArgs e)
{ {
string nts; string nts;
@ -199,7 +199,7 @@ namespace MediaBrowser.Dlna.Ssdp
socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 4); socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 4);
socket.Bind(localEndpoint); socket.Bind(localEndpoint);
return socket; return socket;
} }
@ -248,7 +248,10 @@ namespace MediaBrowser.Dlna.Ssdp
public void Dispose() public void Dispose()
{ {
_ssdpHandler.MessageReceived -= _ssdpHandler_MessageReceived; if (_ssdpHandler != null)
{
_ssdpHandler.MessageReceived -= _ssdpHandler_MessageReceived;
}
if (!_disposed) if (!_disposed)
{ {

@ -125,7 +125,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
if ((attributes & FileAttributes.Directory) == FileAttributes.Directory) if ((attributes & FileAttributes.Directory) == FileAttributes.Directory)
{ {
if (IsSeasonFolder(child.FullName, isTvContentType)) if (IsSeasonFolder(child.FullName, isTvContentType, libraryManager))
{ {
//logger.Debug("{0} is a series because of season folder {1}.", path, child.FullName); //logger.Debug("{0} is a series because of season folder {1}.", path, child.FullName);
return true; return true;
@ -188,10 +188,13 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
/// </summary> /// </summary>
/// <param name="path">The path.</param> /// <param name="path">The path.</param>
/// <param name="isTvContentType">if set to <c>true</c> [is tv content type].</param> /// <param name="isTvContentType">if set to <c>true</c> [is tv content type].</param>
/// <param name="libraryManager">The library manager.</param>
/// <returns><c>true</c> if [is season folder] [the specified path]; otherwise, <c>false</c>.</returns> /// <returns><c>true</c> if [is season folder] [the specified path]; otherwise, <c>false</c>.</returns>
private static bool IsSeasonFolder(string path, bool isTvContentType) private static bool IsSeasonFolder(string path, bool isTvContentType, ILibraryManager libraryManager)
{ {
var seasonNumber = new SeasonPathParser(new ExtendedNamingOptions(), new RegexProvider()).Parse(path, isTvContentType, isTvContentType).SeasonNumber; var namingOptions = ((LibraryManager)libraryManager).GetNamingOptions();
var seasonNumber = new SeasonPathParser(namingOptions, new RegexProvider()).Parse(path, isTvContentType, isTvContentType).SeasonNumber;
return seasonNumber.HasValue; return seasonNumber.HasValue;
} }

@ -350,7 +350,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv.Listings
{ {
url = apiUrl + "/image/" + images.data[logoIndex].uri; url = apiUrl + "/image/" + images.data[logoIndex].uri;
} }
_logger.Debug("URL for image is : " + url); //_logger.Debug("URL for image is : " + url);
} }
return url; return url;
} }

@ -0,0 +1,114 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Dlna;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Logging;
using System;
using System.Linq;
using System.Threading;
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{
public class HdHomerunDiscovery : 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);
public HdHomerunDiscovery(IDeviceDiscovery deviceDiscovery, IServerConfigurationManager config, ILogger logger, ILiveTvManager liveTvManager)
{
_deviceDiscovery = deviceDiscovery;
_config = config;
_logger = logger;
_liveTvManager = liveTvManager;
}
public void Run()
{
_deviceDiscovery.DeviceDiscovered += _deviceDiscovery_DeviceDiscovered;
}
void _deviceDiscovery_DeviceDiscovered(object sender, SsdpMessageEventArgs e)
{
string server = null;
if (e.Headers.TryGetValue("SERVER", out server) && server.IndexOf("HDHomeRun", StringComparison.OrdinalIgnoreCase) != -1)
{
string location;
if (e.Headers.TryGetValue("Location", out location))
{
_logger.Debug("HdHomerun found at {0}", location);
// Just get the beginning of the url
Uri uri;
if (Uri.TryCreate(location, UriKind.Absolute, out uri))
{
var apiUrl = location.Replace(uri.LocalPath, String.Empty, StringComparison.OrdinalIgnoreCase)
.TrimEnd('/');
_logger.Debug("HdHomerun api url: {0}", apiUrl);
AddDevice(apiUrl);
}
}
}
}
private async void AddDevice(string url)
{
await _semaphore.WaitAsync().ConfigureAwait(false);
try
{
var options = GetConfiguration();
if (options.TunerHosts.Any(i =>
string.Equals(i.Type, HdHomerunHost.DeviceType, StringComparison.OrdinalIgnoreCase) &&
UriEquals(i.Url, url)))
{
return;
}
await _liveTvManager.SaveTunerHost(new TunerHostInfo
{
Type = HdHomerunHost.DeviceType,
Url = url
}).ConfigureAwait(false);
}
catch (Exception ex)
{
_logger.ErrorException("Error saving device", ex);
}
finally
{
_semaphore.Release();
}
}
private bool UriEquals(string savedUri, string location)
{
if (!savedUri.StartsWith("http", StringComparison.OrdinalIgnoreCase))
{
savedUri = "http://" + savedUri;
}
savedUri = savedUri.TrimEnd('/');
location = location.TrimEnd('/');
return string.Equals(location, savedUri, StringComparison.OrdinalIgnoreCase);
}
private LiveTvOptions GetConfiguration()
{
return _config.GetConfiguration<LiveTvOptions>("livetv");
}
public void Dispose()
{
}
}
}

@ -15,16 +15,16 @@ using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts.HdHomerun
{ {
public class HdHomerun : ITunerHost public class HdHomerunHost : ITunerHost
{ {
private readonly IHttpClient _httpClient; private readonly IHttpClient _httpClient;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly IJsonSerializer _jsonSerializer; private readonly IJsonSerializer _jsonSerializer;
private readonly IConfigurationManager _config; private readonly IConfigurationManager _config;
public HdHomerun(IHttpClient httpClient, ILogger logger, IJsonSerializer jsonSerializer, IConfigurationManager config) public HdHomerunHost(IHttpClient httpClient, ILogger logger, IJsonSerializer jsonSerializer, IConfigurationManager config)
{ {
_httpClient = httpClient; _httpClient = httpClient;
_logger = logger; _logger = logger;
@ -38,6 +38,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
} }
public string Type public string Type
{
get { return DeviceType; }
}
public static string DeviceType
{ {
get { return "hdhomerun"; } get { return "hdhomerun"; }
} }

@ -226,7 +226,8 @@
<Compile Include="LiveTv\LiveTvDtoService.cs" /> <Compile Include="LiveTv\LiveTvDtoService.cs" />
<Compile Include="LiveTv\LiveTvManager.cs" /> <Compile Include="LiveTv\LiveTvManager.cs" />
<Compile Include="LiveTv\LiveTvMediaSourceProvider.cs" /> <Compile Include="LiveTv\LiveTvMediaSourceProvider.cs" />
<Compile Include="LiveTv\TunerHosts\HdHomerun.cs" /> <Compile Include="LiveTv\TunerHosts\HdHomerun\HdHomerunHost.cs" />
<Compile Include="LiveTv\TunerHosts\HdHomerun\HdHomerunDiscovery.cs" />
<Compile Include="LiveTv\TunerHosts\M3UTunerHost.cs" /> <Compile Include="LiveTv\TunerHosts\M3UTunerHost.cs" />
<Compile Include="LiveTv\ProgramImageProvider.cs" /> <Compile Include="LiveTv\ProgramImageProvider.cs" />
<Compile Include="LiveTv\RecordingImageProvider.cs" /> <Compile Include="LiveTv\RecordingImageProvider.cs" />

@ -514,6 +514,8 @@ namespace MediaBrowser.Server.Startup.Common
SubtitleManager = new SubtitleManager(LogManager.GetLogger("SubtitleManager"), FileSystemManager, LibraryMonitor, LibraryManager, MediaSourceManager); SubtitleManager = new SubtitleManager(LogManager.GetLogger("SubtitleManager"), FileSystemManager, LibraryMonitor, LibraryManager, MediaSourceManager);
RegisterSingleInstance(SubtitleManager); RegisterSingleInstance(SubtitleManager);
RegisterSingleInstance<IDeviceDiscovery>(new DeviceDiscovery(LogManager.GetLogger("IDeviceDiscovery"), ServerConfigurationManager, this));
ChapterManager = new ChapterManager(LibraryManager, LogManager.GetLogger("ChapterManager"), ServerConfigurationManager, ItemRepository); ChapterManager = new ChapterManager(LibraryManager, LogManager.GetLogger("ChapterManager"), ServerConfigurationManager, ItemRepository);
RegisterSingleInstance(ChapterManager); RegisterSingleInstance(ChapterManager);

Loading…
Cancel
Save