mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-11-15 09:59:06 -07:00
add hdhomerun auto-discovery
This commit is contained in:
parent
23bab40308
commit
ffd9460d51
10
MediaBrowser.Controller/Dlna/IDeviceDiscovery.cs
Normal file
10
MediaBrowser.Controller/Dlna/IDeviceDiscovery.cs
Normal file
@ -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\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" />
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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())
|
||||
@ -71,7 +71,7 @@ namespace MediaBrowser.Dlna.Ssdp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void _ssdpHandler_MessageReceived(object sender, SsdpMessageEventArgs e)
|
||||
{
|
||||
string nts;
|
||||
@ -199,7 +199,7 @@ namespace MediaBrowser.Dlna.Ssdp
|
||||
socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 4);
|
||||
|
||||
socket.Bind(localEndpoint);
|
||||
|
||||
|
||||
return socket;
|
||||
}
|
||||
|
||||
@ -248,7 +248,10 @@ namespace MediaBrowser.Dlna.Ssdp
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_ssdpHandler.MessageReceived -= _ssdpHandler_MessageReceived;
|
||||
if (_ssdpHandler != null)
|
||||
{
|
||||
_ssdpHandler.MessageReceived -= _ssdpHandler_MessageReceived;
|
||||
}
|
||||
|
||||
if (!_disposed)
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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.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"; }
|
||||
}
|
@ -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" />
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user