aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Jellyfin.LiveTv/EmbyTV/EntryPoint.cs21
-rw-r--r--src/Jellyfin.LiveTv/EmbyTV/LiveTvHost.cs31
-rw-r--r--src/Jellyfin.LiveTv/RecordingNotifier.cs73
-rw-r--r--src/Jellyfin.Networking/PortForwardingHost.cs (renamed from src/Jellyfin.Networking/ExternalPortForwarding.cs)71
4 files changed, 103 insertions, 93 deletions
diff --git a/src/Jellyfin.LiveTv/EmbyTV/EntryPoint.cs b/src/Jellyfin.LiveTv/EmbyTV/EntryPoint.cs
deleted file mode 100644
index e750c05ac..000000000
--- a/src/Jellyfin.LiveTv/EmbyTV/EntryPoint.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-#pragma warning disable CS1591
-
-using System.Threading.Tasks;
-using MediaBrowser.Controller.Plugins;
-
-namespace Jellyfin.LiveTv.EmbyTV
-{
- public sealed class EntryPoint : IServerEntryPoint
- {
- /// <inheritdoc />
- public Task RunAsync()
- {
- return EmbyTV.Current.Start();
- }
-
- /// <inheritdoc />
- public void Dispose()
- {
- }
- }
-}
diff --git a/src/Jellyfin.LiveTv/EmbyTV/LiveTvHost.cs b/src/Jellyfin.LiveTv/EmbyTV/LiveTvHost.cs
new file mode 100644
index 000000000..dc15d53ff
--- /dev/null
+++ b/src/Jellyfin.LiveTv/EmbyTV/LiveTvHost.cs
@@ -0,0 +1,31 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Controller.LiveTv;
+using Microsoft.Extensions.Hosting;
+
+namespace Jellyfin.LiveTv.EmbyTV;
+
+/// <summary>
+/// <see cref="IHostedService"/> responsible for initializing Live TV.
+/// </summary>
+public sealed class LiveTvHost : IHostedService
+{
+ private readonly EmbyTV _service;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="LiveTvHost"/> class.
+ /// </summary>
+ /// <param name="services">The available <see cref="ILiveTvService"/>s.</param>
+ public LiveTvHost(IEnumerable<ILiveTvService> services)
+ {
+ _service = services.OfType<EmbyTV>().First();
+ }
+
+ /// <inheritdoc />
+ public Task StartAsync(CancellationToken cancellationToken) => _service.Start();
+
+ /// <inheritdoc />
+ public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
+}
diff --git a/src/Jellyfin.LiveTv/RecordingNotifier.cs b/src/Jellyfin.LiveTv/RecordingNotifier.cs
index 2923948eb..226d525e7 100644
--- a/src/Jellyfin.LiveTv/RecordingNotifier.cs
+++ b/src/Jellyfin.LiveTv/RecordingNotifier.cs
@@ -1,7 +1,3 @@
-#nullable disable
-
-#pragma warning disable CS1591
-
using System;
using System.Linq;
using System.Threading;
@@ -10,34 +6,44 @@ using Jellyfin.Data.Enums;
using Jellyfin.Data.Events;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
-using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Session;
+using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace Jellyfin.LiveTv
{
- public sealed class RecordingNotifier : IServerEntryPoint
+ /// <summary>
+ /// <see cref="IHostedService"/> responsible for notifying users when a LiveTV recording is completed.
+ /// </summary>
+ public sealed class RecordingNotifier : IHostedService
{
- private readonly ILiveTvManager _liveTvManager;
+ private readonly ILogger<RecordingNotifier> _logger;
private readonly ISessionManager _sessionManager;
private readonly IUserManager _userManager;
- private readonly ILogger<RecordingNotifier> _logger;
+ private readonly ILiveTvManager _liveTvManager;
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RecordingNotifier"/> class.
+ /// </summary>
+ /// <param name="logger">The <see cref="ILogger"/>.</param>
+ /// <param name="sessionManager">The <see cref="ISessionManager"/>.</param>
+ /// <param name="userManager">The <see cref="IUserManager"/>.</param>
+ /// <param name="liveTvManager">The <see cref="ILiveTvManager"/>.</param>
public RecordingNotifier(
+ ILogger<RecordingNotifier> logger,
ISessionManager sessionManager,
IUserManager userManager,
- ILogger<RecordingNotifier> logger,
ILiveTvManager liveTvManager)
{
+ _logger = logger;
_sessionManager = sessionManager;
_userManager = userManager;
- _logger = logger;
_liveTvManager = liveTvManager;
}
/// <inheritdoc />
- public Task RunAsync()
+ public Task StartAsync(CancellationToken cancellationToken)
{
_liveTvManager.TimerCancelled += OnLiveTvManagerTimerCancelled;
_liveTvManager.SeriesTimerCancelled += OnLiveTvManagerSeriesTimerCancelled;
@@ -47,29 +53,35 @@ namespace Jellyfin.LiveTv
return Task.CompletedTask;
}
- private async void OnLiveTvManagerSeriesTimerCreated(object sender, GenericEventArgs<TimerEventInfo> e)
+ /// <inheritdoc />
+ public Task StopAsync(CancellationToken cancellationToken)
{
- await SendMessage(SessionMessageType.SeriesTimerCreated, e.Argument).ConfigureAwait(false);
- }
+ _liveTvManager.TimerCancelled -= OnLiveTvManagerTimerCancelled;
+ _liveTvManager.SeriesTimerCancelled -= OnLiveTvManagerSeriesTimerCancelled;
+ _liveTvManager.TimerCreated -= OnLiveTvManagerTimerCreated;
+ _liveTvManager.SeriesTimerCreated -= OnLiveTvManagerSeriesTimerCreated;
- private async void OnLiveTvManagerTimerCreated(object sender, GenericEventArgs<TimerEventInfo> e)
- {
- await SendMessage(SessionMessageType.TimerCreated, e.Argument).ConfigureAwait(false);
+ return Task.CompletedTask;
}
- private async void OnLiveTvManagerSeriesTimerCancelled(object sender, GenericEventArgs<TimerEventInfo> e)
- {
- await SendMessage(SessionMessageType.SeriesTimerCancelled, e.Argument).ConfigureAwait(false);
- }
+ private async void OnLiveTvManagerSeriesTimerCreated(object? sender, GenericEventArgs<TimerEventInfo> e)
+ => await SendMessage(SessionMessageType.SeriesTimerCreated, e.Argument).ConfigureAwait(false);
- private async void OnLiveTvManagerTimerCancelled(object sender, GenericEventArgs<TimerEventInfo> e)
- {
- await SendMessage(SessionMessageType.TimerCancelled, e.Argument).ConfigureAwait(false);
- }
+ private async void OnLiveTvManagerTimerCreated(object? sender, GenericEventArgs<TimerEventInfo> e)
+ => await SendMessage(SessionMessageType.TimerCreated, e.Argument).ConfigureAwait(false);
+
+ private async void OnLiveTvManagerSeriesTimerCancelled(object? sender, GenericEventArgs<TimerEventInfo> e)
+ => await SendMessage(SessionMessageType.SeriesTimerCancelled, e.Argument).ConfigureAwait(false);
+
+ private async void OnLiveTvManagerTimerCancelled(object? sender, GenericEventArgs<TimerEventInfo> e)
+ => await SendMessage(SessionMessageType.TimerCancelled, e.Argument).ConfigureAwait(false);
private async Task SendMessage(SessionMessageType name, TimerEventInfo info)
{
- var users = _userManager.Users.Where(i => i.HasPermission(PermissionKind.EnableLiveTvAccess)).Select(i => i.Id).ToList();
+ var users = _userManager.Users
+ .Where(i => i.HasPermission(PermissionKind.EnableLiveTvAccess))
+ .Select(i => i.Id)
+ .ToList();
try
{
@@ -80,14 +92,5 @@ namespace Jellyfin.LiveTv
_logger.LogError(ex, "Error sending message");
}
}
-
- /// <inheritdoc />
- public void Dispose()
- {
- _liveTvManager.TimerCancelled -= OnLiveTvManagerTimerCancelled;
- _liveTvManager.SeriesTimerCancelled -= OnLiveTvManagerSeriesTimerCancelled;
- _liveTvManager.TimerCreated -= OnLiveTvManagerTimerCreated;
- _liveTvManager.SeriesTimerCreated -= OnLiveTvManagerSeriesTimerCreated;
- }
}
}
diff --git a/src/Jellyfin.Networking/ExternalPortForwarding.cs b/src/Jellyfin.Networking/PortForwardingHost.cs
index df9e43ca9..d01343624 100644
--- a/src/Jellyfin.Networking/ExternalPortForwarding.cs
+++ b/src/Jellyfin.Networking/PortForwardingHost.cs
@@ -1,7 +1,3 @@
-#nullable disable
-
-#pragma warning disable CS1591
-
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -12,36 +8,34 @@ using System.Threading.Tasks;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
-using MediaBrowser.Controller.Plugins;
+using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Mono.Nat;
namespace Jellyfin.Networking;
/// <summary>
-/// Server entrypoint handling external port forwarding.
+/// <see cref="IHostedService"/> responsible for UPnP port forwarding.
/// </summary>
-public sealed class ExternalPortForwarding : IServerEntryPoint
+public sealed class PortForwardingHost : IHostedService, IDisposable
{
private readonly IServerApplicationHost _appHost;
- private readonly ILogger<ExternalPortForwarding> _logger;
+ private readonly ILogger<PortForwardingHost> _logger;
private readonly IServerConfigurationManager _config;
+ private readonly ConcurrentDictionary<IPEndPoint, byte> _createdRules = new();
- private readonly ConcurrentDictionary<IPEndPoint, byte> _createdRules = new ConcurrentDictionary<IPEndPoint, byte>();
-
- private Timer _timer;
- private string _configIdentifier;
-
+ private Timer? _timer;
+ private string? _configIdentifier;
private bool _disposed;
/// <summary>
- /// Initializes a new instance of the <see cref="ExternalPortForwarding"/> class.
+ /// Initializes a new instance of the <see cref="PortForwardingHost"/> class.
/// </summary>
/// <param name="logger">The logger.</param>
/// <param name="appHost">The application host.</param>
/// <param name="config">The configuration manager.</param>
- public ExternalPortForwarding(
- ILogger<ExternalPortForwarding> logger,
+ public PortForwardingHost(
+ ILogger<PortForwardingHost> logger,
IServerApplicationHost appHost,
IServerConfigurationManager config)
{
@@ -66,7 +60,7 @@ public sealed class ExternalPortForwarding : IServerEntryPoint
.ToString();
}
- private void OnConfigurationUpdated(object sender, EventArgs e)
+ private void OnConfigurationUpdated(object? sender, EventArgs e)
{
var oldConfigIdentifier = _configIdentifier;
_configIdentifier = GetConfigIdentifier();
@@ -79,7 +73,7 @@ public sealed class ExternalPortForwarding : IServerEntryPoint
}
/// <inheritdoc />
- public Task RunAsync()
+ public Task StartAsync(CancellationToken cancellationToken)
{
Start();
@@ -88,6 +82,14 @@ public sealed class ExternalPortForwarding : IServerEntryPoint
return Task.CompletedTask;
}
+ /// <inheritdoc />
+ public Task StopAsync(CancellationToken cancellationToken)
+ {
+ Stop();
+
+ return Task.CompletedTask;
+ }
+
private void Start()
{
var config = _config.GetNetworkConfiguration();
@@ -101,7 +103,8 @@ public sealed class ExternalPortForwarding : IServerEntryPoint
NatUtility.DeviceFound += OnNatUtilityDeviceFound;
NatUtility.StartDiscovery();
- _timer = new Timer((_) => _createdRules.Clear(), null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10));
+ _timer?.Dispose();
+ _timer = new Timer(_ => _createdRules.Clear(), null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10));
}
private void Stop()
@@ -112,13 +115,23 @@ public sealed class ExternalPortForwarding : IServerEntryPoint
NatUtility.DeviceFound -= OnNatUtilityDeviceFound;
_timer?.Dispose();
+ _timer = null;
}
- private async void OnNatUtilityDeviceFound(object sender, DeviceEventArgs e)
+ private async void OnNatUtilityDeviceFound(object? sender, DeviceEventArgs e)
{
+ ObjectDisposedException.ThrowIf(_disposed, this);
+
try
{
- await CreateRules(e.Device).ConfigureAwait(false);
+ // On some systems the device discovered event seems to fire repeatedly
+ // This check will help ensure we're not trying to port map the same device over and over
+ if (!_createdRules.TryAdd(e.Device.DeviceEndpoint, 0))
+ {
+ return;
+ }
+
+ await Task.WhenAll(CreatePortMaps(e.Device)).ConfigureAwait(false);
}
catch (Exception ex)
{
@@ -126,20 +139,6 @@ public sealed class ExternalPortForwarding : IServerEntryPoint
}
}
- private Task CreateRules(INatDevice device)
- {
- ObjectDisposedException.ThrowIf(_disposed, this);
-
- // On some systems the device discovered event seems to fire repeatedly
- // This check will help ensure we're not trying to port map the same device over and over
- if (!_createdRules.TryAdd(device.DeviceEndpoint, 0))
- {
- return Task.CompletedTask;
- }
-
- return Task.WhenAll(CreatePortMaps(device));
- }
-
private IEnumerable<Task> CreatePortMaps(INatDevice device)
{
var config = _config.GetNetworkConfiguration();
@@ -185,8 +184,6 @@ public sealed class ExternalPortForwarding : IServerEntryPoint
_config.ConfigurationUpdated -= OnConfigurationUpdated;
- Stop();
-
_timer?.Dispose();
_timer = null;