add hdhomerun auto-discovery

This commit is contained in:
Luke Pulverenti 2015-07-23 12:32:34 -04:00
parent 23bab40308
commit ffd9460d51
13 changed files with 169 additions and 45 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -5,7 +5,6 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Session;
using MediaBrowser.Dlna.Didl;
using MediaBrowser.Dlna.Ssdp;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
@ -35,7 +34,7 @@ namespace MediaBrowser.Dlna.PlayTo
private readonly ILocalizationManager _localization;
private readonly IMediaSourceManager _mediaSourceManager;
private readonly DeviceDiscovery _deviceDiscovery;
private readonly IDeviceDiscovery _deviceDiscovery;
private readonly string _serverAddress;
private readonly string _accessToken;
@ -58,7 +57,7 @@ namespace MediaBrowser.Dlna.PlayTo
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;
_sessionManager = sessionManager;

View File

@ -32,13 +32,13 @@ namespace MediaBrowser.Dlna.PlayTo
private readonly IUserDataManager _userDataManager;
private readonly ILocalizationManager _localization;
private readonly DeviceDiscovery _deviceDiscovery;
private readonly IDeviceDiscovery _deviceDiscovery;
private readonly IMediaSourceManager _mediaSourceManager;
private readonly List<string> _nonRendererUrls = new List<string>();
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;
_sessionManager = sessionManager;

View File

@ -14,31 +14,31 @@ using System.Threading.Tasks;
namespace MediaBrowser.Dlna.Ssdp
{
public class DeviceDiscovery : IDisposable
public class DeviceDiscovery : IDeviceDiscovery, IDisposable
{
private bool _disposed;
private readonly ILogger _logger;
private readonly IServerConfigurationManager _config;
private readonly SsdpHandler _ssdpHandler;
private SsdpHandler _ssdpHandler;
private readonly CancellationTokenSource _tokenSource;
private readonly IServerApplicationHost _appHost;
public event EventHandler<SsdpMessageEventArgs> DeviceDiscovered;
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();
_logger = logger;
_config = config;
_ssdpHandler = ssdpHandler;
_appHost = appHost;
}
public void Start()
public void Start(SsdpHandler ssdpHandler)
{
_ssdpHandler = ssdpHandler;
_ssdpHandler.MessageReceived += _ssdpHandler_MessageReceived;
foreach (var network in GetNetworkInterfaces())
@ -247,8 +247,11 @@ namespace MediaBrowser.Dlna.Ssdp
}
public void Dispose()
{
if (_ssdpHandler != null)
{
_ssdpHandler.MessageReceived -= _ssdpHandler_MessageReceived;
}
if (!_disposed)
{

View File

@ -125,7 +125,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
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);
return true;
@ -188,10 +188,13 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
/// </summary>
/// <param name="path">The path.</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>
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;
}

View File

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

View File

@ -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()
{
}
}
}

View File

@ -15,16 +15,16 @@ using System.Linq;
using System.Threading;
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 ILogger _logger;
private readonly IJsonSerializer _jsonSerializer;
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;
_logger = logger;
@ -38,6 +38,11 @@ namespace MediaBrowser.Server.Implementations.LiveTv.TunerHosts
}
public string Type
{
get { return DeviceType; }
}
public static string DeviceType
{
get { return "hdhomerun"; }
}

View File

@ -226,7 +226,8 @@
<Compile Include="LiveTv\LiveTvDtoService.cs" />
<Compile Include="LiveTv\LiveTvManager.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\ProgramImageProvider.cs" />
<Compile Include="LiveTv\RecordingImageProvider.cs" />

View File

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