Ver Fonte

add hdhomerun auto-discovery

Luke Pulverenti há 10 anos atrás
pai
commit
ffd9460d51

+ 10 - 0
MediaBrowser.Controller/Dlna/IDeviceDiscovery.cs

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

+ 1 - 0
MediaBrowser.Controller/MediaBrowser.Controller.csproj

@@ -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" />

+ 5 - 5
MediaBrowser.Dlna/Channels/DlnaChannelFactory.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)

+ 5 - 19
MediaBrowser.Dlna/Main/DlnaEntryPoint.cs

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

+ 2 - 3
MediaBrowser.Dlna/PlayTo/PlayToController.cs

@@ -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;

+ 2 - 2
MediaBrowser.Dlna/PlayTo/PlayToManager.cs

@@ -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;

+ 11 - 8
MediaBrowser.Dlna/Ssdp/DeviceDiscovery.cs

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

+ 6 - 3
MediaBrowser.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs

@@ -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;
         }

+ 1 - 1
MediaBrowser.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs

@@ -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;
         }

+ 114 - 0
MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunDiscovery.cs

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

+ 8 - 3
MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun.cs → MediaBrowser.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs

@@ -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"; }
         }

+ 2 - 1
MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj

@@ -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" />

+ 2 - 0
MediaBrowser.Server.Startup.Common/ApplicationHost.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);