aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CONTRIBUTORS.md1
-rw-r--r--Emby.Notifications/Api/NotificationsService.cs52
-rw-r--r--Emby.Notifications/CoreNotificationTypes.cs3
-rw-r--r--Emby.Notifications/Emby.Notifications.csproj14
-rw-r--r--Emby.Notifications/NotificationConfigurationFactory.cs5
-rw-r--r--Emby.Notifications/NotificationEntryPoint.cs (renamed from Emby.Notifications/Notifications.cs)120
-rw-r--r--Emby.Notifications/NotificationManager.cs39
-rw-r--r--Emby.Photos/Emby.Photos.csproj1
-rw-r--r--Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs10
-rw-r--r--Emby.Server.Implementations/ApplicationHost.cs5
-rw-r--r--Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs34
-rw-r--r--Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs9
-rw-r--r--Emby.Server.Implementations/EntryPoints/StartupWizard.cs15
-rw-r--r--Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs6
-rw-r--r--Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs44
-rw-r--r--Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs2
-rw-r--r--Emby.Server.Implementations/HttpServer/HttpListenerHost.cs27
-rw-r--r--Emby.Server.Implementations/IO/ExtendedFileSystemInfo.cs2
-rw-r--r--Emby.Server.Implementations/IO/FileRefresher.cs40
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs3
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs1
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs3
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs5
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/IRecorder.cs3
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs3
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs18
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs4
-rw-r--r--Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs3
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs3
-rw-r--r--Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs7
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs3
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs3
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvManager.cs2
-rw-r--r--Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs48
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs3
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs3
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs3
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs3
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs3
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs3
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs3
-rw-r--r--Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs3
-rw-r--r--Emby.Server.Implementations/Localization/Core/es_DO.json9
-rw-r--r--Emby.Server.Implementations/Localization/Core/he.json26
-rw-r--r--Emby.Server.Implementations/Localization/Core/ms.json10
-rw-r--r--Emby.Server.Implementations/Localization/Core/nn.json41
-rw-r--r--Emby.Server.Implementations/Localization/Core/sv.json4
-rw-r--r--MediaBrowser.Api/Playback/MediaInfoService.cs93
-rw-r--r--MediaBrowser.Controller/Library/IMediaSourceProvider.cs3
-rw-r--r--MediaBrowser.Model/Users/UserPolicy.cs3
-rw-r--r--jellyfin.ruleset2
-rw-r--r--tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs441
52 files changed, 550 insertions, 644 deletions
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index 2a9779cd5..e14636a57 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -34,6 +34,7 @@
- [ullmie02](https://github.com/ullmie02)
- [geilername](https://github.com/geilername)
- [pR0Ps](https://github.com/pR0Ps)
+ - [artiume](https://github.com/Artiume)
# Emby Contributors
diff --git a/Emby.Notifications/Api/NotificationsService.cs b/Emby.Notifications/Api/NotificationsService.cs
index 83845558a..f2f381838 100644
--- a/Emby.Notifications/Api/NotificationsService.cs
+++ b/Emby.Notifications/Api/NotificationsService.cs
@@ -1,5 +1,11 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1402
+#pragma warning disable SA1600
+#pragma warning disable SA1649
+
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -16,7 +22,7 @@ namespace Emby.Notifications.Api
public class GetNotifications : IReturn<NotificationResult>
{
[ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string UserId { get; set; }
+ public string UserId { get; set; } = string.Empty;
[ApiMember(Name = "IsRead", Description = "An optional filter by IsRead", IsRequired = false, DataType = "bool", ParameterType = "query", Verb = "GET")]
public bool? IsRead { get; set; }
@@ -30,32 +36,34 @@ namespace Emby.Notifications.Api
public class Notification
{
- public string Id { get; set; }
+ public string Id { get; set; } = string.Empty;
- public string UserId { get; set; }
+ public string UserId { get; set; } = string.Empty;
public DateTime Date { get; set; }
public bool IsRead { get; set; }
- public string Name { get; set; }
+ public string Name { get; set; } = string.Empty;
- public string Description { get; set; }
+ public string Description { get; set; } = string.Empty;
- public string Url { get; set; }
+ public string Url { get; set; } = string.Empty;
public NotificationLevel Level { get; set; }
}
public class NotificationResult
{
- public Notification[] Notifications { get; set; }
+ public IReadOnlyList<Notification> Notifications { get; set; } = Array.Empty<Notification>();
+
public int TotalRecordCount { get; set; }
}
public class NotificationsSummary
{
public int UnreadCount { get; set; }
+
public NotificationLevel MaxUnreadNotificationLevel { get; set; }
}
@@ -63,7 +71,7 @@ namespace Emby.Notifications.Api
public class GetNotificationsSummary : IReturn<NotificationsSummary>
{
[ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "GET")]
- public string UserId { get; set; }
+ public string UserId { get; set; } = string.Empty;
}
[Route("/Notifications/Types", "GET", Summary = "Gets notification types")]
@@ -80,16 +88,16 @@ namespace Emby.Notifications.Api
public class AddAdminNotification : IReturnVoid
{
[ApiMember(Name = "Name", Description = "The notification's name", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Name { get; set; }
+ public string Name { get; set; } = string.Empty;
[ApiMember(Name = "Description", Description = "The notification's description", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Description { get; set; }
+ public string Description { get; set; } = string.Empty;
[ApiMember(Name = "ImageUrl", Description = "The notification's image url", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string ImageUrl { get; set; }
+ public string? ImageUrl { get; set; }
[ApiMember(Name = "Url", Description = "The notification's info url", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
- public string Url { get; set; }
+ public string? Url { get; set; }
[ApiMember(Name = "Level", Description = "The notification level", IsRequired = false, DataType = "string", ParameterType = "query", Verb = "POST")]
public NotificationLevel Level { get; set; }
@@ -99,20 +107,20 @@ namespace Emby.Notifications.Api
public class MarkRead : IReturnVoid
{
[ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string UserId { get; set; }
+ public string UserId { get; set; } = string.Empty;
[ApiMember(Name = "Ids", Description = "A list of notification ids, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)]
- public string Ids { get; set; }
+ public string Ids { get; set; } = string.Empty;
}
[Route("/Notifications/{UserId}/Unread", "POST", Summary = "Marks notifications as unread")]
public class MarkUnread : IReturnVoid
{
[ApiMember(Name = "UserId", Description = "User Id", IsRequired = true, DataType = "string", ParameterType = "path", Verb = "POST")]
- public string UserId { get; set; }
+ public string UserId { get; set; } = string.Empty;
[ApiMember(Name = "Ids", Description = "A list of notification ids, comma delimited", IsRequired = true, DataType = "string", ParameterType = "query", Verb = "POST", AllowMultiple = true)]
- public string Ids { get; set; }
+ public string Ids { get; set; } = string.Empty;
}
[Authenticated]
@@ -127,32 +135,29 @@ namespace Emby.Notifications.Api
_userManager = userManager;
}
+ [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request")]
public object Get(GetNotificationTypes request)
{
return _notificationManager.GetNotificationTypes();
}
+ [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request")]
public object Get(GetNotificationServices request)
{
return _notificationManager.GetNotificationServices().ToList();
}
+ [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request")]
public object Get(GetNotificationsSummary request)
{
return new NotificationsSummary
{
-
};
}
public Task Post(AddAdminNotification request)
{
// This endpoint really just exists as post of a real with sickbeard
- return AddNotification(request);
- }
-
- private Task AddNotification(AddAdminNotification request)
- {
var notification = new NotificationRequest
{
Date = DateTime.UtcNow,
@@ -166,14 +171,17 @@ namespace Emby.Notifications.Api
return _notificationManager.SendNotification(notification, CancellationToken.None);
}
+ [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request")]
public void Post(MarkRead request)
{
}
+ [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request")]
public void Post(MarkUnread request)
{
}
+ [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "request")]
public object Get(GetNotifications request)
{
return new NotificationResult();
diff --git a/Emby.Notifications/CoreNotificationTypes.cs b/Emby.Notifications/CoreNotificationTypes.cs
index d11e01e33..73e0b0256 100644
--- a/Emby.Notifications/CoreNotificationTypes.cs
+++ b/Emby.Notifications/CoreNotificationTypes.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System;
using System.Collections.Generic;
using System.Linq;
diff --git a/Emby.Notifications/Emby.Notifications.csproj b/Emby.Notifications/Emby.Notifications.csproj
index 004ded77b..e6bf785bf 100644
--- a/Emby.Notifications/Emby.Notifications.csproj
+++ b/Emby.Notifications/Emby.Notifications.csproj
@@ -4,6 +4,8 @@
<TargetFramework>netstandard2.1</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
+ <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
@@ -16,4 +18,16 @@
<ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj" />
</ItemGroup>
+ <!-- Code analyzers-->
+ <ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8" PrivateAssets="All" />
+ <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
+ <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
+ </ItemGroup>
+
+ <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
+ <CodeAnalysisRuleSet>../jellyfin.ruleset</CodeAnalysisRuleSet>
+ </PropertyGroup>
+
</Project>
diff --git a/Emby.Notifications/NotificationConfigurationFactory.cs b/Emby.Notifications/NotificationConfigurationFactory.cs
index d08475f7d..b168ed221 100644
--- a/Emby.Notifications/NotificationConfigurationFactory.cs
+++ b/Emby.Notifications/NotificationConfigurationFactory.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System.Collections.Generic;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Model.Notifications;
@@ -13,7 +16,7 @@ namespace Emby.Notifications
new ConfigurationStore
{
Key = "notifications",
- ConfigurationType = typeof (NotificationOptions)
+ ConfigurationType = typeof(NotificationOptions)
}
};
}
diff --git a/Emby.Notifications/Notifications.cs b/Emby.Notifications/NotificationEntryPoint.cs
index 7aa1e7ae8..befecc570 100644
--- a/Emby.Notifications/Notifications.cs
+++ b/Emby.Notifications/NotificationEntryPoint.cs
@@ -21,70 +21,85 @@ using Microsoft.Extensions.Logging;
namespace Emby.Notifications
{
/// <summary>
- /// Creates notifications for various system events
+ /// Creates notifications for various system events.
/// </summary>
- public class Notifications : IServerEntryPoint
+ public class NotificationEntryPoint : IServerEntryPoint
{
private readonly ILogger _logger;
-
+ private readonly IActivityManager _activityManager;
+ private readonly ILocalizationManager _localization;
private readonly INotificationManager _notificationManager;
-
private readonly ILibraryManager _libraryManager;
private readonly IServerApplicationHost _appHost;
+ private readonly IConfigurationManager _config;
- private Timer LibraryUpdateTimer { get; set; }
private readonly object _libraryChangedSyncLock = new object();
+ private readonly List<BaseItem> _itemsAdded = new List<BaseItem>();
- private readonly IConfigurationManager _config;
- private readonly ILocalizationManager _localization;
- private readonly IActivityManager _activityManager;
+ private Timer? _libraryUpdateTimer;
private string[] _coreNotificationTypes;
- public Notifications(
+ private bool _disposed = false;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="NotificationEntryPoint" /> class.
+ /// </summary>
+ /// <param name="logger">The logger.</param>
+ /// <param name="activityManager">The activity manager.</param>
+ /// <param name="localization">The localization manager.</param>
+ /// <param name="notificationManager">The notification manager.</param>
+ /// <param name="libraryManager">The library manager.</param>
+ /// <param name="appHost">The application host.</param>
+ /// <param name="config">The configuration manager.</param>
+ public NotificationEntryPoint(
+ ILogger<NotificationEntryPoint> logger,
IActivityManager activityManager,
ILocalizationManager localization,
- ILogger logger,
INotificationManager notificationManager,
ILibraryManager libraryManager,
IServerApplicationHost appHost,
IConfigurationManager config)
{
_logger = logger;
+ _activityManager = activityManager;
+ _localization = localization;
_notificationManager = notificationManager;
_libraryManager = libraryManager;
_appHost = appHost;
_config = config;
- _localization = localization;
- _activityManager = activityManager;
_coreNotificationTypes = new CoreNotificationTypes(localization).GetNotificationTypes().Select(i => i.Type).ToArray();
}
+ /// <inheritdoc />
public Task RunAsync()
{
- _libraryManager.ItemAdded += _libraryManager_ItemAdded;
- _appHost.HasPendingRestartChanged += _appHost_HasPendingRestartChanged;
- _appHost.HasUpdateAvailableChanged += _appHost_HasUpdateAvailableChanged;
- _activityManager.EntryCreated += _activityManager_EntryCreated;
+ _libraryManager.ItemAdded += OnLibraryManagerItemAdded;
+ _appHost.HasPendingRestartChanged += OnAppHostHasPendingRestartChanged;
+ _appHost.HasUpdateAvailableChanged += OnAppHostHasUpdateAvailableChanged;
+ _activityManager.EntryCreated += OnActivityManagerEntryCreated;
return Task.CompletedTask;
}
- private async void _appHost_HasPendingRestartChanged(object sender, EventArgs e)
+ private async void OnAppHostHasPendingRestartChanged(object sender, EventArgs e)
{
var type = NotificationType.ServerRestartRequired.ToString();
var notification = new NotificationRequest
{
NotificationType = type,
- Name = string.Format(_localization.GetLocalizedString("ServerNameNeedsToBeRestarted"), _appHost.Name)
+ Name = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("ServerNameNeedsToBeRestarted"),
+ _appHost.Name)
};
await SendNotification(notification, null).ConfigureAwait(false);
}
- private async void _activityManager_EntryCreated(object sender, GenericEventArgs<ActivityLogEntry> e)
+ private async void OnActivityManagerEntryCreated(object sender, GenericEventArgs<ActivityLogEntry> e)
{
var entry = e.Argument;
@@ -117,7 +132,7 @@ namespace Emby.Notifications
return _config.GetConfiguration<NotificationOptions>("notifications");
}
- private async void _appHost_HasUpdateAvailableChanged(object sender, EventArgs e)
+ private async void OnAppHostHasUpdateAvailableChanged(object sender, EventArgs e)
{
if (!_appHost.HasUpdateAvailable)
{
@@ -136,8 +151,7 @@ namespace Emby.Notifications
await SendNotification(notification, null).ConfigureAwait(false);
}
- private readonly List<BaseItem> _itemsAdded = new List<BaseItem>();
- private void _libraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
+ private void OnLibraryManagerItemAdded(object sender, ItemChangeEventArgs e)
{
if (!FilterItem(e.Item))
{
@@ -146,14 +160,17 @@ namespace Emby.Notifications
lock (_libraryChangedSyncLock)
{
- if (LibraryUpdateTimer == null)
+ if (_libraryUpdateTimer == null)
{
- LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, 5000,
- Timeout.Infinite);
+ _libraryUpdateTimer = new Timer(
+ LibraryUpdateTimerCallback,
+ null,
+ 5000,
+ Timeout.Infinite);
}
else
{
- LibraryUpdateTimer.Change(5000, Timeout.Infinite);
+ _libraryUpdateTimer.Change(5000, Timeout.Infinite);
}
_itemsAdded.Add(e.Item);
@@ -188,7 +205,8 @@ namespace Emby.Notifications
{
items = _itemsAdded.ToList();
_itemsAdded.Clear();
- DisposeLibraryUpdateTimer();
+ _libraryUpdateTimer!.Dispose(); // Shouldn't be null as it just set off this callback
+ _libraryUpdateTimer = null;
}
items = items.Take(10).ToList();
@@ -198,7 +216,10 @@ namespace Emby.Notifications
var notification = new NotificationRequest
{
NotificationType = NotificationType.NewLibraryContent.ToString(),
- Name = string.Format(_localization.GetLocalizedString("ValueHasBeenAddedToLibrary"), GetItemName(item)),
+ Name = string.Format(
+ CultureInfo.InvariantCulture,
+ _localization.GetLocalizedString("ValueHasBeenAddedToLibrary"),
+ GetItemName(item)),
Description = item.Overview
};
@@ -206,6 +227,11 @@ namespace Emby.Notifications
}
}
+ /// <summary>
+ /// Creates a human readable name for the item.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <returns>A human readable name for the item.</returns>
public static string GetItemName(BaseItem item)
{
var name = item.Name;
@@ -219,6 +245,7 @@ namespace Emby.Notifications
episode.IndexNumber.Value,
name);
}
+
if (episode.ParentIndexNumber.HasValue)
{
name = string.Format(
@@ -229,7 +256,6 @@ namespace Emby.Notifications
}
}
-
if (item is IHasSeries hasSeries)
{
name = hasSeries.SeriesName + " - " + name;
@@ -257,7 +283,7 @@ namespace Emby.Notifications
return name;
}
- private async Task SendNotification(NotificationRequest notification, BaseItem relatedItem)
+ private async Task SendNotification(NotificationRequest notification, BaseItem? relatedItem)
{
try
{
@@ -269,23 +295,37 @@ namespace Emby.Notifications
}
}
+ /// <inheritdoc />
public void Dispose()
{
- DisposeLibraryUpdateTimer();
-
- _libraryManager.ItemAdded -= _libraryManager_ItemAdded;
- _appHost.HasPendingRestartChanged -= _appHost_HasPendingRestartChanged;
- _appHost.HasUpdateAvailableChanged -= _appHost_HasUpdateAvailableChanged;
- _activityManager.EntryCreated -= _activityManager_EntryCreated;
+ Dispose(true);
+ GC.SuppressFinalize(this);
}
- private void DisposeLibraryUpdateTimer()
+ /// <summary>
+ /// Releases unmanaged and optionally managed resources.
+ /// </summary>
+ /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
+ protected virtual void Dispose(bool disposing)
{
- if (LibraryUpdateTimer != null)
+ if (_disposed)
+ {
+ return;
+ }
+
+ if (disposing)
{
- LibraryUpdateTimer.Dispose();
- LibraryUpdateTimer = null;
+ _libraryUpdateTimer?.Dispose();
}
+
+ _libraryUpdateTimer = null;
+
+ _libraryManager.ItemAdded -= OnLibraryManagerItemAdded;
+ _appHost.HasPendingRestartChanged -= OnAppHostHasPendingRestartChanged;
+ _appHost.HasUpdateAvailableChanged -= OnAppHostHasUpdateAvailableChanged;
+ _activityManager.EntryCreated -= OnActivityManagerEntryCreated;
+
+ _disposed = true;
}
}
}
diff --git a/Emby.Notifications/NotificationManager.cs b/Emby.Notifications/NotificationManager.cs
index eecbbea07..639a5e1aa 100644
--- a/Emby.Notifications/NotificationManager.cs
+++ b/Emby.Notifications/NotificationManager.cs
@@ -16,20 +16,32 @@ using Microsoft.Extensions.Logging;
namespace Emby.Notifications
{
+ /// <summary>
+ /// NotificationManager class.
+ /// </summary>
public class NotificationManager : INotificationManager
{
private readonly ILogger _logger;
private readonly IUserManager _userManager;
private readonly IServerConfigurationManager _config;
- private INotificationService[] _services;
- private INotificationTypeFactory[] _typeFactories;
-
- public NotificationManager(ILoggerFactory loggerFactory, IUserManager userManager, IServerConfigurationManager config)
+ private INotificationService[] _services = Array.Empty<INotificationService>();
+ private INotificationTypeFactory[] _typeFactories = Array.Empty<INotificationTypeFactory>();
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="NotificationManager" /> class.
+ /// </summary>
+ /// <param name="logger">The logger.</param>
+ /// <param name="userManager">The user manager.</param>
+ /// <param name="config">The server configuration manager.</param>
+ public NotificationManager(
+ ILogger<NotificationManager> logger,
+ IUserManager userManager,
+ IServerConfigurationManager config)
{
+ _logger = logger;
_userManager = userManager;
_config = config;
- _logger = loggerFactory.CreateLogger(GetType().Name);
}
private NotificationOptions GetConfiguration()
@@ -37,12 +49,14 @@ namespace Emby.Notifications
return _config.GetConfiguration<NotificationOptions>("notifications");
}
+ /// <inheritdoc />
public Task SendNotification(NotificationRequest request, CancellationToken cancellationToken)
{
return SendNotification(request, null, cancellationToken);
}
- public Task SendNotification(NotificationRequest request, BaseItem relatedItem, CancellationToken cancellationToken)
+ /// <inheritdoc />
+ public Task SendNotification(NotificationRequest request, BaseItem? relatedItem, CancellationToken cancellationToken)
{
var notificationType = request.NotificationType;
@@ -64,7 +78,8 @@ namespace Emby.Notifications
return Task.WhenAll(tasks);
}
- private Task SendNotification(NotificationRequest request,
+ private Task SendNotification(
+ NotificationRequest request,
INotificationService service,
IEnumerable<User> users,
string title,
@@ -79,7 +94,7 @@ namespace Emby.Notifications
return Task.WhenAll(tasks);
}
- private IEnumerable<Guid> GetUserIds(NotificationRequest request, NotificationOption options)
+ private IEnumerable<Guid> GetUserIds(NotificationRequest request, NotificationOption? options)
{
if (request.SendToUserMode.HasValue)
{
@@ -109,7 +124,8 @@ namespace Emby.Notifications
return request.UserIds;
}
- private async Task SendNotification(NotificationRequest request,
+ private async Task SendNotification(
+ NotificationRequest request,
INotificationService service,
string title,
string description,
@@ -161,12 +177,14 @@ namespace Emby.Notifications
return GetConfiguration().IsServiceEnabled(service.Name, notificationType);
}
+ /// <inheritdoc />
public void AddParts(IEnumerable<INotificationService> services, IEnumerable<INotificationTypeFactory> notificationTypeFactories)
{
_services = services.ToArray();
_typeFactories = notificationTypeFactories.ToArray();
}
+ /// <inheritdoc />
public List<NotificationTypeInfo> GetNotificationTypes()
{
var list = _typeFactories.Select(i =>
@@ -180,7 +198,6 @@ namespace Emby.Notifications
_logger.LogError(ex, "Error in GetNotificationTypes");
return new List<NotificationTypeInfo>();
}
-
}).SelectMany(i => i).ToList();
var config = GetConfiguration();
@@ -193,13 +210,13 @@ namespace Emby.Notifications
return list;
}
+ /// <inheritdoc />
public IEnumerable<NameIdPair> GetNotificationServices()
{
return _services.Select(i => new NameIdPair
{
Name = i.Name,
Id = i.Name.GetMD5().ToString("N", CultureInfo.InvariantCulture)
-
}).OrderBy(i => i.Name);
}
}
diff --git a/Emby.Photos/Emby.Photos.csproj b/Emby.Photos/Emby.Photos.csproj
index ed6918dba..cc3fbb43f 100644
--- a/Emby.Photos/Emby.Photos.csproj
+++ b/Emby.Photos/Emby.Photos.csproj
@@ -17,6 +17,7 @@
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
+ <Nullable>enable</Nullable>
</PropertyGroup>
<!-- Code Analyzers-->
diff --git a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs
index ac8af66a2..4664eadd3 100644
--- a/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs
+++ b/Emby.Server.Implementations/Activity/ActivityLogEntryPoint.cs
@@ -29,7 +29,7 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.Activity
{
- public class ActivityLogEntryPoint : IServerEntryPoint
+ public sealed class ActivityLogEntryPoint : IServerEntryPoint
{
private readonly ILogger _logger;
private readonly IInstallationManager _installationManager;
@@ -39,7 +39,6 @@ namespace Emby.Server.Implementations.Activity
private readonly ILocalizationManager _localization;
private readonly ISubtitleManager _subManager;
private readonly IUserManager _userManager;
- private readonly IServerApplicationHost _appHost;
private readonly IDeviceManager _deviceManager;
/// <summary>
@@ -64,8 +63,7 @@ namespace Emby.Server.Implementations.Activity
ILocalizationManager localization,
IInstallationManager installationManager,
ISubtitleManager subManager,
- IUserManager userManager,
- IServerApplicationHost appHost)
+ IUserManager userManager)
{
_logger = logger;
_sessionManager = sessionManager;
@@ -76,7 +74,6 @@ namespace Emby.Server.Implementations.Activity
_installationManager = installationManager;
_subManager = subManager;
_userManager = userManager;
- _appHost = appHost;
}
public Task RunAsync()
@@ -141,7 +138,7 @@ namespace Emby.Server.Implementations.Activity
CultureInfo.InvariantCulture,
_localization.GetLocalizedString("SubtitleDownloadFailureFromForItem"),
e.Provider,
- Notifications.Notifications.GetItemName(e.Item)),
+ Emby.Notifications.NotificationEntryPoint.GetItemName(e.Item)),
Type = "SubtitleDownloadFailure",
ItemId = e.Item.Id.ToString("N", CultureInfo.InvariantCulture),
ShortOverview = e.Exception.Message
@@ -533,6 +530,7 @@ namespace Emby.Server.Implementations.Activity
private void CreateLogEntry(ActivityLogEntry entry)
=> _activityManager.Create(entry);
+ /// <inheritdoc />
public void Dispose()
{
_taskManager.TaskCompleted -= OnTaskCompleted;
diff --git a/Emby.Server.Implementations/ApplicationHost.cs b/Emby.Server.Implementations/ApplicationHost.cs
index fd0112266..8ea188724 100644
--- a/Emby.Server.Implementations/ApplicationHost.cs
+++ b/Emby.Server.Implementations/ApplicationHost.cs
@@ -847,7 +847,10 @@ namespace Emby.Server.Implementations
UserViewManager = new UserViewManager(LibraryManager, LocalizationManager, UserManager, ChannelManager, LiveTvManager, ServerConfigurationManager);
serviceCollection.AddSingleton(UserViewManager);
- NotificationManager = new NotificationManager(LoggerFactory, UserManager, ServerConfigurationManager);
+ NotificationManager = new NotificationManager(
+ LoggerFactory.CreateLogger<NotificationManager>(),
+ UserManager,
+ ServerConfigurationManager);
serviceCollection.AddSingleton(NotificationManager);
serviceCollection.AddSingleton<IDeviceDiscovery>(new DeviceDiscovery(ServerConfigurationManager));
diff --git a/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs b/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs
index e0aa18e89..9603d7976 100644
--- a/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs
+++ b/Emby.Server.Implementations/EntryPoints/RecordingNotifier.cs
@@ -13,7 +13,7 @@ using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.EntryPoints
{
- public class RecordingNotifier : IServerEntryPoint
+ public sealed class RecordingNotifier : IServerEntryPoint
{
private readonly ILiveTvManager _liveTvManager;
private readonly ISessionManager _sessionManager;
@@ -28,32 +28,33 @@ namespace Emby.Server.Implementations.EntryPoints
_liveTvManager = liveTvManager;
}
+ /// <inheritdoc />
public Task RunAsync()
{
- _liveTvManager.TimerCancelled += _liveTvManager_TimerCancelled;
- _liveTvManager.SeriesTimerCancelled += _liveTvManager_SeriesTimerCancelled;
- _liveTvManager.TimerCreated += _liveTvManager_TimerCreated;
- _liveTvManager.SeriesTimerCreated += _liveTvManager_SeriesTimerCreated;
+ _liveTvManager.TimerCancelled += OnLiveTvManagerTimerCancelled;
+ _liveTvManager.SeriesTimerCancelled += OnLiveTvManagerSeriesTimerCancelled;
+ _liveTvManager.TimerCreated += OnLiveTvManagerTimerCreated;
+ _liveTvManager.SeriesTimerCreated += OnLiveTvManagerSeriesTimerCreated;
return Task.CompletedTask;
}
- private void _liveTvManager_SeriesTimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
+ private void OnLiveTvManagerSeriesTimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
{
SendMessage("SeriesTimerCreated", e.Argument);
}
- private void _liveTvManager_TimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
+ private void OnLiveTvManagerTimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
{
SendMessage("TimerCreated", e.Argument);
}
- private void _liveTvManager_SeriesTimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
+ private void OnLiveTvManagerSeriesTimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
{
SendMessage("SeriesTimerCancelled", e.Argument);
}
- private void _liveTvManager_TimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
+ private void OnLiveTvManagerTimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
{
SendMessage("TimerCancelled", e.Argument);
}
@@ -64,11 +65,7 @@ namespace Emby.Server.Implementations.EntryPoints
try
{
- await _sessionManager.SendMessageToUserSessions(users, name, info, CancellationToken.None);
- }
- catch (ObjectDisposedException)
- {
- // TODO Log exception or Investigate and properly fix.
+ await _sessionManager.SendMessageToUserSessions(users, name, info, CancellationToken.None).ConfigureAwait(false);
}
catch (Exception ex)
{
@@ -76,12 +73,13 @@ namespace Emby.Server.Implementations.EntryPoints
}
}
+ /// <inheritdoc />
public void Dispose()
{
- _liveTvManager.TimerCancelled -= _liveTvManager_TimerCancelled;
- _liveTvManager.SeriesTimerCancelled -= _liveTvManager_SeriesTimerCancelled;
- _liveTvManager.TimerCreated -= _liveTvManager_TimerCreated;
- _liveTvManager.SeriesTimerCreated -= _liveTvManager_SeriesTimerCreated;
+ _liveTvManager.TimerCancelled -= OnLiveTvManagerTimerCancelled;
+ _liveTvManager.SeriesTimerCancelled -= OnLiveTvManagerSeriesTimerCancelled;
+ _liveTvManager.TimerCreated -= OnLiveTvManagerTimerCreated;
+ _liveTvManager.SeriesTimerCreated -= OnLiveTvManagerSeriesTimerCreated;
}
}
}
diff --git a/Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs b/Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs
index f00996b5f..54f4b67e6 100644
--- a/Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs
+++ b/Emby.Server.Implementations/EntryPoints/RefreshUsersMetadata.cs
@@ -6,7 +6,6 @@ using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Tasks;
-using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.EntryPoints
{
@@ -15,21 +14,17 @@ namespace Emby.Server.Implementations.EntryPoints
/// </summary>
public class RefreshUsersMetadata : IScheduledTask, IConfigurableScheduledTask
{
- private readonly ILogger _logger;
-
/// <summary>
/// The user manager.
/// </summary>
private readonly IUserManager _userManager;
-
- private IFileSystem _fileSystem;
+ private readonly IFileSystem _fileSystem;
/// <summary>
/// Initializes a new instance of the <see cref="RefreshUsersMetadata" /> class.
/// </summary>
- public RefreshUsersMetadata(ILogger logger, IUserManager userManager, IFileSystem fileSystem)
+ public RefreshUsersMetadata(IUserManager userManager, IFileSystem fileSystem)
{
- _logger = logger;
_userManager = userManager;
_fileSystem = fileSystem;
}
diff --git a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs
index 161788c63..5f2d629fe 100644
--- a/Emby.Server.Implementations/EntryPoints/StartupWizard.cs
+++ b/Emby.Server.Implementations/EntryPoints/StartupWizard.cs
@@ -3,37 +3,28 @@ using Emby.Server.Implementations.Browser;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Plugins;
-using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.EntryPoints
{
/// <summary>
/// Class StartupWizard.
/// </summary>
- public class StartupWizard : IServerEntryPoint
+ public sealed class StartupWizard : IServerEntryPoint
{
/// <summary>
/// The app host.
/// </summary>
private readonly IServerApplicationHost _appHost;
-
- /// <summary>
- /// The user manager.
- /// </summary>
- private readonly ILogger _logger;
-
- private IServerConfigurationManager _config;
+ private readonly IServerConfigurationManager _config;
/// <summary>
/// Initializes a new instance of the <see cref="StartupWizard"/> class.
/// </summary>
/// <param name="appHost">The application host.</param>
- /// <param name="logger">The logger.</param>
/// <param name="config">The configuration manager.</param>
- public StartupWizard(IServerApplicationHost appHost, ILogger logger, IServerConfigurationManager config)
+ public StartupWizard(IServerApplicationHost appHost, IServerConfigurationManager config)
{
_appHost = appHost;
- _logger = logger;
_config = config;
}
diff --git a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs
index 529f83560..50ba0f8fa 100644
--- a/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs
+++ b/Emby.Server.Implementations/EntryPoints/UdpServerEntryPoint.cs
@@ -3,8 +3,6 @@ using System.Threading.Tasks;
using Emby.Server.Implementations.Udp;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Plugins;
-using MediaBrowser.Model.Net;
-using MediaBrowser.Model.Serialization;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.EntryPoints
@@ -23,9 +21,7 @@ namespace Emby.Server.Implementations.EntryPoints
/// The logger.
/// </summary>
private readonly ILogger _logger;
- private readonly ISocketFactory _socketFactory;
private readonly IServerApplicationHost _appHost;
- private readonly IJsonSerializer _json;
/// <summary>
/// The UDP server.
@@ -64,7 +60,7 @@ namespace Emby.Server.Implementations.EntryPoints
_cancellationTokenSource.Cancel();
_udpServer.Dispose();
-
+ _cancellationTokenSource.Dispose();
_cancellationTokenSource = null;
_udpServer = null;
diff --git a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs
index 3e22080fc..026b5dae9 100644
--- a/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs
+++ b/Emby.Server.Implementations/EntryPoints/UserDataChangeNotifier.cs
@@ -13,39 +13,38 @@ using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Session;
-using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.EntryPoints
{
- public class UserDataChangeNotifier : IServerEntryPoint
+ public sealed class UserDataChangeNotifier : IServerEntryPoint
{
+ private const int UpdateDuration = 500;
+
private readonly ISessionManager _sessionManager;
- private readonly ILogger _logger;
private readonly IUserDataManager _userDataManager;
private readonly IUserManager _userManager;
+ private readonly Dictionary<Guid, List<BaseItem>> _changedItems = new Dictionary<Guid, List<BaseItem>>();
+
private readonly object _syncLock = new object();
- private Timer UpdateTimer { get; set; }
- private const int UpdateDuration = 500;
+ private Timer _updateTimer;
- private readonly Dictionary<Guid, List<BaseItem>> _changedItems = new Dictionary<Guid, List<BaseItem>>();
- public UserDataChangeNotifier(IUserDataManager userDataManager, ISessionManager sessionManager, ILogger logger, IUserManager userManager)
+ public UserDataChangeNotifier(IUserDataManager userDataManager, ISessionManager sessionManager, IUserManager userManager)
{
_userDataManager = userDataManager;
_sessionManager = sessionManager;
- _logger = logger;
_userManager = userManager;
}
public Task RunAsync()
{
- _userDataManager.UserDataSaved += _userDataManager_UserDataSaved;
+ _userDataManager.UserDataSaved += OnUserDataManagerUserDataSaved;
return Task.CompletedTask;
}
- void _userDataManager_UserDataSaved(object sender, UserDataSaveEventArgs e)
+ void OnUserDataManagerUserDataSaved(object sender, UserDataSaveEventArgs e)
{
if (e.SaveReason == UserDataSaveReason.PlaybackProgress)
{
@@ -54,14 +53,17 @@ namespace Emby.Server.Implementations.EntryPoints
lock (_syncLock)
{
- if (UpdateTimer == null)
+ if (_updateTimer == null)
{
- UpdateTimer = new Timer(UpdateTimerCallback, null, UpdateDuration,
- Timeout.Infinite);
+ _updateTimer = new Timer(
+ UpdateTimerCallback,
+ null,
+ UpdateDuration,
+ Timeout.Infinite);
}
else
{
- UpdateTimer.Change(UpdateDuration, Timeout.Infinite);
+ _updateTimer.Change(UpdateDuration, Timeout.Infinite);
}
if (!_changedItems.TryGetValue(e.UserId, out List<BaseItem> keys))
@@ -97,10 +99,10 @@ namespace Emby.Server.Implementations.EntryPoints
var task = SendNotifications(changes, CancellationToken.None);
- if (UpdateTimer != null)
+ if (_updateTimer != null)
{
- UpdateTimer.Dispose();
- UpdateTimer = null;
+ _updateTimer.Dispose();
+ _updateTimer = null;
}
}
}
@@ -145,13 +147,13 @@ namespace Emby.Server.Implementations.EntryPoints
public void Dispose()
{
- if (UpdateTimer != null)
+ if (_updateTimer != null)
{
- UpdateTimer.Dispose();
- UpdateTimer = null;
+ _updateTimer.Dispose();
+ _updateTimer = null;
}
- _userDataManager.UserDataSaved -= _userDataManager_UserDataSaved;
+ _userDataManager.UserDataSaved -= OnUserDataManagerUserDataSaved;
}
}
}
diff --git a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs
index 8a2bc83fb..45fa03cdd 100644
--- a/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs
+++ b/Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs
@@ -78,7 +78,7 @@ namespace Emby.Server.Implementations.HttpClientManager
if (!string.IsNullOrWhiteSpace(userInfo))
{
_logger.LogWarning("Found userInfo in url: {0} ... url: {1}", userInfo, url);
- url = url.Replace(userInfo + '@', string.Empty);
+ url = url.Replace(userInfo + '@', string.Empty, StringComparison.Ordinal);
}
var request = new HttpRequestMessage(method, url);
diff --git a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
index b0126f7fa..85602a67f 100644
--- a/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
+++ b/Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
@@ -40,9 +40,9 @@ namespace Emby.Server.Implementations.HttpServer
private readonly Func<Type, Func<string, object>> _funcParseFn;
private readonly string _defaultRedirectPath;
private readonly string _baseUrlPrefix;
- private readonly Dictionary<Type, Type> ServiceOperationsMap = new Dictionary<Type, Type>();
- private IWebSocketListener[] _webSocketListeners = Array.Empty<IWebSocketListener>();
+ private readonly Dictionary<Type, Type> _serviceOperationsMap = new Dictionary<Type, Type>();
private readonly List<IWebSocketConnection> _webSocketConnections = new List<IWebSocketConnection>();
+ private IWebSocketListener[] _webSocketListeners = Array.Empty<IWebSocketListener>();
private bool _disposed = false;
public HttpListenerHost(
@@ -72,6 +72,8 @@ namespace Emby.Server.Implementations.HttpServer
ResponseFilters = Array.Empty<Action<IRequest, HttpResponse, object>>();
}
+ public event EventHandler<GenericEventArgs<IWebSocketConnection>> WebSocketConnected;
+
public Action<IRequest, HttpResponse, object>[] ResponseFilters { get; set; }
public static HttpListenerHost Instance { get; protected set; }
@@ -82,8 +84,6 @@ namespace Emby.Server.Implementations.HttpServer
public ServiceController ServiceController { get; private set; }
- public event EventHandler<GenericEventArgs<IWebSocketConnection>> WebSocketConnected;
-
public object CreateInstance(Type type)
{
return _appHost.CreateInstance(type);
@@ -91,7 +91,7 @@ namespace Emby.Server.Implementations.HttpServer
private static string NormalizeUrlPath(string path)
{
- if (path.StartsWith("/"))
+ if (path.Length > 0 && path[0] == '/')
{
// If the path begins with a leading slash, just return it as-is
return path;
@@ -131,13 +131,13 @@ namespace Emby.Server.Implementations.HttpServer
public Type GetServiceTypeByRequest(Type requestType)
{
- ServiceOperationsMap.TryGetValue(requestType, out var serviceType);
+ _serviceOperationsMap.TryGetValue(requestType, out var serviceType);
return serviceType;
}
public void AddServiceInfo(Type serviceType, Type requestType)
{
- ServiceOperationsMap[requestType] = serviceType;
+ _serviceOperationsMap[requestType] = serviceType;
}
private List<IHasRequestFilter> GetRequestFilterAttributes(Type requestDtoType)
@@ -199,7 +199,7 @@ namespace Emby.Server.Implementations.HttpServer
else
{
var inners = agg.InnerExceptions;
- if (inners != null && inners.Count > 0)
+ if (inners.Count > 0)
{
return GetActualException(inners[0]);
}
@@ -362,7 +362,7 @@ namespace Emby.Server.Implementations.HttpServer
return true;
}
- host = host ?? string.Empty;
+ host ??= string.Empty;
if (_networkManager.IsInPrivateAddressSpace(host))
{
@@ -433,7 +433,7 @@ namespace Emby.Server.Implementations.HttpServer
}
/// <summary>
- /// Overridable method that can be used to implement a custom hnandler
+ /// Overridable method that can be used to implement a custom handler.
/// </summary>
public async Task RequestHandler(IHttpRequest httpReq, string urlString, string host, string localPath, CancellationToken cancellationToken)
{
@@ -492,7 +492,7 @@ namespace Emby.Server.Implementations.HttpServer
|| string.Equals(localPath, _baseUrlPrefix, StringComparison.OrdinalIgnoreCase)
|| string.Equals(localPath, "/", StringComparison.OrdinalIgnoreCase)
|| string.IsNullOrEmpty(localPath)
- || !localPath.StartsWith(_baseUrlPrefix))
+ || !localPath.StartsWith(_baseUrlPrefix, StringComparison.OrdinalIgnoreCase))
{
// Always redirect back to the default path if the base prefix is invalid or missing
_logger.LogDebug("Normalizing a URL at {0}", localPath);
@@ -693,7 +693,10 @@ namespace Emby.Server.Implementations.HttpServer
protected virtual void Dispose(bool disposing)
{
- if (_disposed) return;
+ if (_disposed)
+ {
+ return;
+ }
if (disposing)
{
diff --git a/Emby.Server.Implementations/IO/ExtendedFileSystemInfo.cs b/Emby.Server.Implementations/IO/ExtendedFileSystemInfo.cs
index 5be144452..ec26324c3 100644
--- a/Emby.Server.Implementations/IO/ExtendedFileSystemInfo.cs
+++ b/Emby.Server.Implementations/IO/ExtendedFileSystemInfo.cs
@@ -6,7 +6,9 @@ namespace Emby.Server.Implementations.IO
public class ExtendedFileSystemInfo
{
public bool IsHidden { get; set; }
+
public bool IsReadOnly { get; set; }
+
public bool Exists { get; set; }
}
}
diff --git a/Emby.Server.Implementations/IO/FileRefresher.cs b/Emby.Server.Implementations/IO/FileRefresher.cs
index cf92ddbcd..f37a6af90 100644
--- a/Emby.Server.Implementations/IO/FileRefresher.cs
+++ b/Emby.Server.Implementations/IO/FileRefresher.cs
@@ -15,27 +15,29 @@ namespace Emby.Server.Implementations.IO
{
public class FileRefresher : IDisposable
{
- private ILogger Logger { get; set; }
- private ILibraryManager LibraryManager { get; set; }
- private IServerConfigurationManager ConfigurationManager { get; set; }
+ private readonly ILogger _logger;
+ private readonly ILibraryManager _libraryManager;
+ private readonly IServerConfigurationManager _configurationManager;
+
private readonly List<string> _affectedPaths = new List<string>();
- private Timer _timer;
private readonly object _timerLock = new object();
- public string Path { get; private set; }
-
- public event EventHandler<EventArgs> Completed;
+ private Timer _timer;
public FileRefresher(string path, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, ILogger logger)
{
logger.LogDebug("New file refresher created for {0}", path);
Path = path;
- ConfigurationManager = configurationManager;
- LibraryManager = libraryManager;
- Logger = logger;
+ _configurationManager = configurationManager;
+ _libraryManager = libraryManager;
+ _logger = logger;
AddPath(path);
}
+ public event EventHandler<EventArgs> Completed;
+
+ public string Path { get; private set; }
+
private void AddAffectedPath(string path)
{
if (string.IsNullOrEmpty(path))
@@ -80,11 +82,11 @@ namespace Emby.Server.Implementations.IO
if (_timer == null)
{
- _timer = new Timer(OnTimerCallback, null, TimeSpan.FromSeconds(ConfigurationManager.Configuration.LibraryMonitorDelay), TimeSpan.FromMilliseconds(-1));
+ _timer = new Timer(OnTimerCallback, null, TimeSpan.FromSeconds(_configurationManager.Configuration.LibraryMonitorDelay), TimeSpan.FromMilliseconds(-1));
}
else
{
- _timer.Change(TimeSpan.FromSeconds(ConfigurationManager.Configuration.LibraryMonitorDelay), TimeSpan.FromMilliseconds(-1));
+ _timer.Change(TimeSpan.FromSeconds(_configurationManager.Configuration.LibraryMonitorDelay), TimeSpan.FromMilliseconds(-1));
}
}
}
@@ -93,7 +95,7 @@ namespace Emby.Server.Implementations.IO
{
lock (_timerLock)
{
- Logger.LogDebug("Resetting file refresher from {0} to {1}", Path, path);
+ _logger.LogDebug("Resetting file refresher from {0} to {1}", Path, path);
Path = path;
AddAffectedPath(path);
@@ -116,7 +118,7 @@ namespace Emby.Server.Implementations.IO
paths = _affectedPaths.ToList();
}
- Logger.LogDebug("Timer stopped.");
+ _logger.LogDebug("Timer stopped.");
DisposeTimer();
Completed?.Invoke(this, EventArgs.Empty);
@@ -127,7 +129,7 @@ namespace Emby.Server.Implementations.IO
}
catch (Exception ex)
{
- Logger.LogError(ex, "Error processing directory changes");
+ _logger.LogError(ex, "Error processing directory changes");
}
}
@@ -147,7 +149,7 @@ namespace Emby.Server.Implementations.IO
continue;
}
- Logger.LogInformation("{name} ({path}) will be refreshed.", item.Name, item.Path);
+ _logger.LogInformation("{name} ({path}) will be refreshed.", item.Name, item.Path);
try
{
@@ -158,11 +160,11 @@ namespace Emby.Server.Implementations.IO
// For now swallow and log.
// Research item: If an IOException occurs, the item may be in a disconnected state (media unavailable)
// Should we remove it from it's parent?
- Logger.LogError(ex, "Error refreshing {name}", item.Name);
+ _logger.LogError(ex, "Error refreshing {name}", item.Name);
}
catch (Exception ex)
{
- Logger.LogError(ex, "Error refreshing {name}", item.Name);
+ _logger.LogError(ex, "Error refreshing {name}", item.Name);
}
}
}
@@ -178,7 +180,7 @@ namespace Emby.Server.Implementations.IO
while (item == null && !string.IsNullOrEmpty(path))
{
- item = LibraryManager.FindByPath(path, null);
+ item = _libraryManager.FindByPath(path, null);
path = System.IO.Path.GetDirectoryName(path);
}
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs
index 161cf6051..9c4f5fe3d 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/DirectRecorder.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System;
using System.IO;
using System.Net.Http;
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
index 4ac48e537..49d4ddbaf 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EmbyTV.cs
@@ -30,7 +30,6 @@ using MediaBrowser.Model.Diagnostics;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Events;
-using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.MediaInfo;
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
index 6e4ac2fec..8590c56df 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EncodedRecorder.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System;
using System.Collections.Generic;
using System.Globalization;
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs
index 9c9ba09f5..a716b6240 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System.Threading.Tasks;
using MediaBrowser.Controller.Plugins;
@@ -5,11 +8,13 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
public class EntryPoint : IServerEntryPoint
{
+ /// <inheritdoc />
public Task RunAsync()
{
return EmbyTV.Current.Start();
}
+ /// <inheritdoc />
public void Dispose()
{
}
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/IRecorder.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/IRecorder.cs
index 6eced3050..d6a1aee38 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/IRecorder.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/IRecorder.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System;
using System.Threading;
using System.Threading.Tasks;
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs
index 9055a70a6..6d42a58f4 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/ItemDataProvider.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System;
using System.Collections.Generic;
using System.IO;
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs
index ded3c7607..4cb9f6fe8 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/RecordingHelper.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System;
using System.Globalization;
using MediaBrowser.Controller.LiveTv;
@@ -21,7 +24,11 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
if (info.SeasonNumber.HasValue && info.EpisodeNumber.HasValue)
{
- name += string.Format(" S{0}E{1}", info.SeasonNumber.Value.ToString("00", CultureInfo.InvariantCulture), info.EpisodeNumber.Value.ToString("00", CultureInfo.InvariantCulture));
+ name += string.Format(
+ CultureInfo.InvariantCulture,
+ " S{0}E{1}",
+ info.SeasonNumber.Value.ToString("00", CultureInfo.InvariantCulture),
+ info.EpisodeNumber.Value.ToString("00", CultureInfo.InvariantCulture));
addHyphen = false;
}
else if (info.OriginalAirDate.HasValue)
@@ -32,7 +39,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
}
else
{
- name += " " + info.OriginalAirDate.Value.ToLocalTime().ToString("yyyy-MM-dd");
+ name += " " + info.OriginalAirDate.Value.ToLocalTime().ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
}
}
else
@@ -67,14 +74,15 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
date = date.ToLocalTime();
- return string.Format("{0}_{1}_{2}_{3}_{4}_{5}",
+ return string.Format(
+ CultureInfo.InvariantCulture,
+ "{0}_{1}_{2}_{3}_{4}_{5}",
date.Year.ToString("0000", CultureInfo.InvariantCulture),
date.Month.ToString("00", CultureInfo.InvariantCulture),
date.Day.ToString("00", CultureInfo.InvariantCulture),
date.Hour.ToString("00", CultureInfo.InvariantCulture),
date.Minute.ToString("00", CultureInfo.InvariantCulture),
- date.Second.ToString("00", CultureInfo.InvariantCulture)
- );
+ date.Second.ToString("00", CultureInfo.InvariantCulture));
}
}
}
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs
index 520b44404..9cc53fddc 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/SeriesTimerManager.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Model.Serialization;
@@ -12,6 +15,7 @@ namespace Emby.Server.Implementations.LiveTv.EmbyTV
{
}
+ /// <inheritdoc />
public override void Add(SeriesTimerInfo item)
{
if (string.IsNullOrEmpty(item.Id))
diff --git a/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs b/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs
index d09b281d4..330e881ef 100644
--- a/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs
+++ b/Emby.Server.Implementations/LiveTv/EmbyTV/TimerManager.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System;
using System.Collections.Concurrent;
using System.Globalization;
diff --git a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
index 1dd794da0..906f42d2e 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/SchedulesDirect.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
diff --git a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs
index 1f38de2d8..42daa98f5 100644
--- a/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs
+++ b/Emby.Server.Implementations/LiveTv/Listings/XmlTvListingsProvider.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System;
using System.Collections.Generic;
using System.Globalization;
@@ -91,12 +94,12 @@ namespace Emby.Server.Implementations.LiveTv.Listings
{
using (var gzStream = new GZipStream(stream, CompressionMode.Decompress))
{
- await gzStream.CopyToAsync(fileStream).ConfigureAwait(false);
+ await gzStream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false);
}
}
else
{
- await stream.CopyToAsync(fileStream).ConfigureAwait(false);
+ await stream.CopyToAsync(fileStream, cancellationToken).ConfigureAwait(false);
}
}
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs b/Emby.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs
index f9b274acb..222fed9d9 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvConfigurationFactory.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System.Collections.Generic;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Model.LiveTv;
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs
index e584664c9..14b627f82 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvDtoService.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System;
using System.Globalization;
using System.Linq;
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
index e3f9df35a..f20f6140e 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvManager.cs
@@ -1,5 +1,5 @@
-#pragma warning disable SA1600
#pragma warning disable CS1591
+#pragma warning disable SA1600
using System;
using System.Collections.Generic;
diff --git a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
index 52d60c004..33887bbfd 100644
--- a/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
+++ b/Emby.Server.Implementations/LiveTv/LiveTvMediaSourceProvider.cs
@@ -1,52 +1,48 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.LiveTv;
-using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.MediaInfo;
-using MediaBrowser.Model.Serialization;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.LiveTv
{
public class LiveTvMediaSourceProvider : IMediaSourceProvider
{
+ // Do not use a pipe here because Roku http requests to the server will fail, without any explicit error message.
+ private const char StreamIdDelimeter = '_';
+ private const string StreamIdDelimeterString = "_";
+
private readonly ILiveTvManager _liveTvManager;
- private readonly IJsonSerializer _jsonSerializer;
private readonly ILogger _logger;
private readonly IMediaSourceManager _mediaSourceManager;
- private readonly IMediaEncoder _mediaEncoder;
private readonly IServerApplicationHost _appHost;
- private IApplicationPaths _appPaths;
- public LiveTvMediaSourceProvider(ILiveTvManager liveTvManager, IApplicationPaths appPaths, IJsonSerializer jsonSerializer, ILoggerFactory loggerFactory, IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder, IServerApplicationHost appHost)
+ public LiveTvMediaSourceProvider(ILiveTvManager liveTvManager, ILogger<LiveTvMediaSourceProvider> logger, IMediaSourceManager mediaSourceManager, IServerApplicationHost appHost)
{
_liveTvManager = liveTvManager;
- _jsonSerializer = jsonSerializer;
+ _logger = logger;
_mediaSourceManager = mediaSourceManager;
- _mediaEncoder = mediaEncoder;
_appHost = appHost;
- _logger = loggerFactory.CreateLogger(GetType().Name);
- _appPaths = appPaths;
}
public Task<IEnumerable<MediaSourceInfo>> GetMediaSources(BaseItem item, CancellationToken cancellationToken)
{
- var baseItem = (BaseItem)item;
-
- if (baseItem.SourceType == SourceType.LiveTV)
+ if (item.SourceType == SourceType.LiveTV)
{
var activeRecordingInfo = _liveTvManager.GetActiveRecordingInfo(item.Path);
- if (string.IsNullOrEmpty(baseItem.Path) || activeRecordingInfo != null)
+ if (string.IsNullOrEmpty(item.Path) || activeRecordingInfo != null)
{
return GetMediaSourcesInternal(item, activeRecordingInfo, cancellationToken);
}
@@ -55,10 +51,6 @@ namespace Emby.Server.Implementations.LiveTv
return Task.FromResult<IEnumerable<MediaSourceInfo>>(Array.Empty<MediaSourceInfo>());
}
- // Do not use a pipe here because Roku http requests to the server will fail, without any explicit error message.
- private const char StreamIdDelimeter = '_';
- private const string StreamIdDelimeterString = "_";
-
private async Task<IEnumerable<MediaSourceInfo>> GetMediaSourcesInternal(BaseItem item, ActiveRecordingInfo activeRecordingInfo, CancellationToken cancellationToken)
{
IEnumerable<MediaSourceInfo> sources;
@@ -91,7 +83,7 @@ namespace Emby.Server.Implementations.LiveTv
foreach (var source in list)
{
source.Type = MediaSourceType.Default;
- source.BufferMs = source.BufferMs ?? 1500;
+ source.BufferMs ??= 1500;
if (source.RequiresOpening || forceRequireOpening)
{
@@ -100,11 +92,14 @@ namespace Emby.Server.Implementations.LiveTv
if (source.RequiresOpening)
{
- var openKeys = new List<string>();
- openKeys.Add(item.GetType().Name);
- openKeys.Add(item.Id.ToString("N", CultureInfo.InvariantCulture));
- openKeys.Add(source.Id ?? string.Empty);
- source.OpenToken = string.Join(StreamIdDelimeterString, openKeys.ToArray());
+ var openKeys = new List<string>
+ {
+ item.GetType().Name,
+ item.Id.ToString("N", CultureInfo.InvariantCulture),
+ source.Id ?? string.Empty
+ };
+
+ source.OpenToken = string.Join(StreamIdDelimeterString, openKeys);
}
// Dummy this up so that direct play checks can still run
@@ -114,11 +109,12 @@ namespace Emby.Server.Implementations.LiveTv
}
}
- _logger.LogDebug("MediaSources: {0}", _jsonSerializer.SerializeToString(list));
+ _logger.LogDebug("MediaSources: {@MediaSources}", list);
return list;
}
+ /// <inheritdoc />
public async Task<ILiveStream> OpenMediaSource(string openToken, List<ILiveStream> currentLiveStreams, CancellationToken cancellationToken)
{
var keys = openToken.Split(new[] { StreamIdDelimeter }, 3);
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs
index 715f600a1..419ec3635 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/BaseTunerHost.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
index 06f27fa3e..e5cb6c7b9 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System;
using System.Collections.Generic;
using System.Globalization;
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs
index 9702392b2..56864ab11 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System;
using System.Buffers;
using System.Collections.Generic;
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
index 649becbd3..77669da39 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System;
using System.Collections.Generic;
using System.IO;
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs
index 862b9fdfe..5354489f9 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/LiveStream.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System;
using System.Collections.Generic;
using System.Globalization;
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
index df054f1eb..46c77e7b0 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3UTunerHost.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System;
using System.Collections.Generic;
using System.Globalization;
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs
index 51f61bac7..511af150b 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/M3uParser.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System;
using System.Collections.Generic;
using System.Globalization;
diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs
index 99244eb62..861518387 100644
--- a/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs
+++ b/Emby.Server.Implementations/LiveTv/TunerHosts/SharedHttpStream.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System;
using System.Collections.Generic;
using System.IO;
diff --git a/Emby.Server.Implementations/Localization/Core/es_DO.json b/Emby.Server.Implementations/Localization/Core/es_DO.json
index 1ac8d3ae4..1a7b57c53 100644
--- a/Emby.Server.Implementations/Localization/Core/es_DO.json
+++ b/Emby.Server.Implementations/Localization/Core/es_DO.json
@@ -10,5 +10,12 @@
"CameraImageUploadedFrom": "Se ha subido una nueva imagen de cámara desde {0}",
"AuthenticationSucceededWithUserName": "{0} autenticado con éxito",
"Application": "Aplicación",
- "AppDeviceValues": "App: {0}, Dispositivo: {1}"
+ "AppDeviceValues": "App: {0}, Dispositivo: {1}",
+ "HeaderContinueWatching": "Continuar Viendo",
+ "HeaderCameraUploads": "Subidas de Cámara",
+ "HeaderAlbumArtists": "Artistas del Álbum",
+ "Genres": "Géneros",
+ "Folders": "Carpetas",
+ "Favorites": "Favoritos",
+ "FailedLoginAttemptWithUserName": "Intento de inicio de sesión fallido de {0}"
}
diff --git a/Emby.Server.Implementations/Localization/Core/he.json b/Emby.Server.Implementations/Localization/Core/he.json
index b08c8966e..5ef59797d 100644
--- a/Emby.Server.Implementations/Localization/Core/he.json
+++ b/Emby.Server.Implementations/Localization/Core/he.json
@@ -28,7 +28,7 @@
"HeaderRecordingGroups": "קבוצות הקלטה",
"HomeVideos": "סרטונים בייתים",
"Inherit": "הורש",
- "ItemAddedWithName": "{0} was added to the library",
+ "ItemAddedWithName": "{0} הוסף לספרייה",
"ItemRemovedWithName": "{0} נמחק מהספרייה",
"LabelIpAddressValue": "Ip כתובת: {0}",
"LabelRunningTimeValue": "משך צפייה: {0}",
@@ -36,15 +36,15 @@
"MessageApplicationUpdated": "שרת הJellyfin עודכן",
"MessageApplicationUpdatedTo": "שרת הJellyfin עודכן לגרסא {0}",
"MessageNamedServerConfigurationUpdatedWithValue": "הגדרת השרת {0} שונתה",
- "MessageServerConfigurationUpdated": "Server configuration has been updated",
+ "MessageServerConfigurationUpdated": "תצורת השרת עודכנה",
"MixedContent": "תוכן מעורב",
"Movies": "סרטים",
"Music": "מוזיקה",
"MusicVideos": "Music videos",
"NameInstallFailed": "{0} installation failed",
- "NameSeasonNumber": "Season {0}",
- "NameSeasonUnknown": "Season Unknown",
- "NewVersionIsAvailable": "A new version of Jellyfin Server is available for download.",
+ "NameSeasonNumber": "עונה {0}",
+ "NameSeasonUnknown": "עונה לא ידועה",
+ "NewVersionIsAvailable": "גרסה חדשה של שרת Jellyfin זמינה להורדה.",
"NotificationOptionApplicationUpdateAvailable": "Application update available",
"NotificationOptionApplicationUpdateInstalled": "Application update installed",
"NotificationOptionAudioPlayback": "Audio playback started",
@@ -53,10 +53,10 @@
"NotificationOptionInstallationFailed": "התקנה נכשלה",
"NotificationOptionNewLibraryContent": "New content added",
"NotificationOptionPluginError": "Plugin failure",
- "NotificationOptionPluginInstalled": "Plugin installed",
- "NotificationOptionPluginUninstalled": "Plugin uninstalled",
- "NotificationOptionPluginUpdateInstalled": "Plugin update installed",
- "NotificationOptionServerRestartRequired": "Server restart required",
+ "NotificationOptionPluginInstalled": "התוסף הותקן",
+ "NotificationOptionPluginUninstalled": "התוסף הוסר",
+ "NotificationOptionPluginUpdateInstalled": "העדכון לתוסף הותקן",
+ "NotificationOptionServerRestartRequired": "יש לאתחל את השרת",
"NotificationOptionTaskFailed": "Scheduled task failure",
"NotificationOptionUserLockedOut": "User locked out",
"NotificationOptionVideoPlayback": "Video playback started",
@@ -71,15 +71,15 @@
"ScheduledTaskFailedWithName": "{0} failed",
"ScheduledTaskStartedWithName": "{0} started",
"ServerNameNeedsToBeRestarted": "{0} needs to be restarted",
- "Shows": "Shows",
- "Songs": "Songs",
- "StartupEmbyServerIsLoading": "Jellyfin Server is loading. Please try again shortly.",
+ "Shows": "סדרות",
+ "Songs": "שירים",
+ "StartupEmbyServerIsLoading": "שרת Jellyfin בהליכי טעינה. אנא נסה שנית בעוד זמן קצר.",
"SubtitleDownloadFailureForItem": "Subtitles failed to download for {0}",
"SubtitleDownloadFailureFromForItem": "Subtitles failed to download from {0} for {1}",
"SubtitlesDownloadedForItem": "Subtitles downloaded for {0}",
"Sync": "סנכרן",
"System": "System",
- "TvShows": "TV Shows",
+ "TvShows": "סדרות טלוויזיה",
"User": "User",
"UserCreatedWithName": "User {0} has been created",
"UserDeletedWithName": "User {0} has been deleted",
diff --git a/Emby.Server.Implementations/Localization/Core/ms.json b/Emby.Server.Implementations/Localization/Core/ms.json
index b91c98ca0..1d86257f8 100644
--- a/Emby.Server.Implementations/Localization/Core/ms.json
+++ b/Emby.Server.Implementations/Localization/Core/ms.json
@@ -1,9 +1,9 @@
{
"Albums": "Album-album",
- "AppDeviceValues": "App: {0}, Device: {1}",
+ "AppDeviceValues": "Apl: {0}, Peranti: {1}",
"Application": "Aplikasi",
- "Artists": "Artis-artis",
- "AuthenticationSucceededWithUserName": "{0} successfully authenticated",
+ "Artists": "Artis",
+ "AuthenticationSucceededWithUserName": "{0} berjaya disahkan",
"Books": "Buku-buku",
"CameraImageUploadedFrom": "A new camera image has been uploaded from {0}",
"Channels": "Saluran",
@@ -30,7 +30,7 @@
"Inherit": "Inherit",
"ItemAddedWithName": "{0} was added to the library",
"ItemRemovedWithName": "{0} was removed from the library",
- "LabelIpAddressValue": "Ip address: {0}",
+ "LabelIpAddressValue": "Alamat IP: {0}",
"LabelRunningTimeValue": "Running time: {0}",
"Latest": "Latest",
"MessageApplicationUpdated": "Jellyfin Server has been updated",
@@ -50,7 +50,7 @@
"NotificationOptionAudioPlayback": "Audio playback started",
"NotificationOptionAudioPlaybackStopped": "Audio playback stopped",
"NotificationOptionCameraImageUploaded": "Camera image uploaded",
- "NotificationOptionInstallationFailed": "Installation failure",
+ "NotificationOptionInstallationFailed": "Pemasangan gagal",
"NotificationOptionNewLibraryContent": "New content added",
"NotificationOptionPluginError": "Plugin failure",
"NotificationOptionPluginInstalled": "Plugin installed",
diff --git a/Emby.Server.Implementations/Localization/Core/nn.json b/Emby.Server.Implementations/Localization/Core/nn.json
index 0967ef424..ec6da213f 100644
--- a/Emby.Server.Implementations/Localization/Core/nn.json
+++ b/Emby.Server.Implementations/Localization/Core/nn.json
@@ -1 +1,40 @@
-{}
+{
+ "MessageServerConfigurationUpdated": "Tenar konfigurasjonen har blitt oppdatert",
+ "MessageNamedServerConfigurationUpdatedWithValue": "Tenar konfigurasjon seksjon {0} har blitt oppdatert",
+ "MessageApplicationUpdatedTo": "Jellyfin Tenaren har blitt oppdatert til {0}",
+ "MessageApplicationUpdated": "Jellyfin Tenaren har blitt oppdatert",
+ "Latest": "Nyaste",
+ "LabelRunningTimeValue": "Speletid: {0}",
+ "LabelIpAddressValue": "IP adresse: {0}",
+ "ItemRemovedWithName": "{0} vart fjerna frå biblioteket",
+ "ItemAddedWithName": "{0} vart lagt til i biblioteket",
+ "Inherit": "Arv",
+ "HomeVideos": "Heime Videoar",
+ "HeaderRecordingGroups": "Innspelingsgrupper",
+ "HeaderNextUp": "Neste",
+ "HeaderLiveTV": "Direkte TV",
+ "HeaderFavoriteSongs": "Favoritt Songar",
+ "HeaderFavoriteShows": "Favoritt Seriar",
+ "HeaderFavoriteEpisodes": "Favoritt Episodar",
+ "HeaderFavoriteArtists": "Favoritt Artistar",
+ "HeaderFavoriteAlbums": "Favoritt Album",
+ "HeaderContinueWatching": "Fortsett å sjå",
+ "HeaderCameraUploads": "Kamera Opplastingar",
+ "HeaderAlbumArtists": "Album Artist",
+ "Genres": "Sjangrar",
+ "Folders": "Mapper",
+ "Favorites": "Favorittar",
+ "FailedLoginAttemptWithUserName": "Mislukka påloggingsforsøk frå {0}",
+ "DeviceOnlineWithName": "{0} er tilkopla",
+ "DeviceOfflineWithName": "{0} har kopla frå",
+ "Collections": "Samlingar",
+ "ChapterNameValue": "Kapittel {0}",
+ "Channels": "Kanalar",
+ "CameraImageUploadedFrom": "Eit nytt kamera bilete har blitt lasta opp frå {0}",
+ "Books": "Bøker",
+ "AuthenticationSucceededWithUserName": "{0} Har logga inn",
+ "Artists": "Artistar",
+ "Application": "Program",
+ "AppDeviceValues": "App: {0}, Einheit: {1}",
+ "Albums": "Album"
+}
diff --git a/Emby.Server.Implementations/Localization/Core/sv.json b/Emby.Server.Implementations/Localization/Core/sv.json
index 744b0e2d3..db4cfde95 100644
--- a/Emby.Server.Implementations/Localization/Core/sv.json
+++ b/Emby.Server.Implementations/Localization/Core/sv.json
@@ -17,14 +17,14 @@
"Genres": "Genrer",
"HeaderAlbumArtists": "Albumartister",
"HeaderCameraUploads": "Kamera Uppladdningar",
- "HeaderContinueWatching": "Fortsätt kolla på",
+ "HeaderContinueWatching": "Fortsätt kolla",
"HeaderFavoriteAlbums": "Favoritalbum",
"HeaderFavoriteArtists": "Favoritartister",
"HeaderFavoriteEpisodes": "Favoritavsnitt",
"HeaderFavoriteShows": "Favoritserier",
"HeaderFavoriteSongs": "Favoritlåtar",
"HeaderLiveTV": "Live-TV",
- "HeaderNextUp": "Nästa på tur",
+ "HeaderNextUp": "Nästa",
"HeaderRecordingGroups": "Inspelningsgrupper",
"HomeVideos": "Hemvideor",
"Inherit": "Ärv",
diff --git a/MediaBrowser.Api/Playback/MediaInfoService.cs b/MediaBrowser.Api/Playback/MediaInfoService.cs
index 0eb184d14..a44e1720f 100644
--- a/MediaBrowser.Api/Playback/MediaInfoService.cs
+++ b/MediaBrowser.Api/Playback/MediaInfoService.cs
@@ -412,10 +412,12 @@ namespace MediaBrowser.Api.Playback
user.Policy.EnableAudioPlaybackTranscoding);
}
+ // Beginning of Playback Determination: Attempt DirectPlay first
if (mediaSource.SupportsDirectPlay)
{
- if (mediaSource.IsRemote && forceDirectPlayRemoteMediaSource)
+ if (mediaSource.IsRemote && user.Policy.ForceRemoteSourceTranscoding)
{
+ mediaSource.SupportsDirectPlay = false;
}
else
{
@@ -462,36 +464,43 @@ namespace MediaBrowser.Api.Playback
if (mediaSource.SupportsDirectStream)
{
- options.MaxBitrate = GetMaxBitrate(maxBitrate, user);
-
- if (item is Audio)
+ if (mediaSource.IsRemote && user.Policy.ForceRemoteSourceTranscoding)
{
- if (!user.Policy.EnableAudioPlaybackTranscoding)
- {
- options.ForceDirectStream = true;
- }
+ mediaSource.SupportsDirectStream = false;
}
- else if (item is Video)
+ else
{
- if (!user.Policy.EnableAudioPlaybackTranscoding && !user.Policy.EnableVideoPlaybackTranscoding && !user.Policy.EnablePlaybackRemuxing)
+ options.MaxBitrate = GetMaxBitrate(maxBitrate, user);
+
+ if (item is Audio)
{
- options.ForceDirectStream = true;
+ if (!user.Policy.EnableAudioPlaybackTranscoding)
+ {
+ options.ForceDirectStream = true;
+ }
+ }
+ else if (item is Video)
+ {
+ if (!user.Policy.EnableAudioPlaybackTranscoding && !user.Policy.EnableVideoPlaybackTranscoding && !user.Policy.EnablePlaybackRemuxing)
+ {
+ options.ForceDirectStream = true;
+ }
}
- }
// The MediaSource supports direct stream, now test to see if the client supports it
var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase)
? streamBuilder.BuildAudioItem(options)
: streamBuilder.BuildVideoItem(options);
- if (streamInfo == null || !streamInfo.IsDirectStream)
- {
- mediaSource.SupportsDirectStream = false;
- }
+ if (streamInfo == null || !streamInfo.IsDirectStream)
+ {
+ mediaSource.SupportsDirectStream = false;
+ }
- if (streamInfo != null)
- {
- SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token);
+ if (streamInfo != null)
+ {
+ SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token);
+ }
}
}
@@ -504,18 +513,46 @@ namespace MediaBrowser.Api.Playback
? streamBuilder.BuildAudioItem(options)
: streamBuilder.BuildVideoItem(options);
- if (streamInfo != null)
+ if (mediaSource.IsRemote && user.Policy.ForceRemoteSourceTranscoding)
{
- streamInfo.PlaySessionId = playSessionId;
-
- if (streamInfo.PlayMethod == PlayMethod.Transcode)
+ if (streamInfo != null)
{
+ streamInfo.PlaySessionId = playSessionId;
streamInfo.StartPositionTicks = startTimeTicks;
mediaSource.TranscodingUrl = streamInfo.ToUrl("-", auth.Token).TrimStart('-');
+ mediaSource.TranscodingUrl += "&allowVideoStreamCopy=false";
+ if (!allowAudioStreamCopy)
+ {
+ mediaSource.TranscodingUrl += "&allowAudioStreamCopy=false";
+ }
+ mediaSource.TranscodingContainer = streamInfo.Container;
+ mediaSource.TranscodingSubProtocol = streamInfo.SubProtocol;
+
+ // Do this after the above so that StartPositionTicks is set
+ SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token);
+ }
+ }
+ else
+ {
+ if (streamInfo != null)
+ {
+ streamInfo.PlaySessionId = playSessionId;
- if (!allowVideoStreamCopy)
+ if (streamInfo.PlayMethod == PlayMethod.Transcode)
{
- mediaSource.TranscodingUrl += "&allowVideoStreamCopy=false";
+ streamInfo.StartPositionTicks = startTimeTicks;
+ mediaSource.TranscodingUrl = streamInfo.ToUrl("-", auth.Token).TrimStart('-');
+
+ if (!allowVideoStreamCopy)
+ {
+ mediaSource.TranscodingUrl += "&allowVideoStreamCopy=false";
+ }
+ if (!allowAudioStreamCopy)
+ {
+ mediaSource.TranscodingUrl += "&allowAudioStreamCopy=false";
+ }
+ mediaSource.TranscodingContainer = streamInfo.Container;
+ mediaSource.TranscodingSubProtocol = streamInfo.SubProtocol;
}
if (!allowAudioStreamCopy)
@@ -525,10 +562,10 @@ namespace MediaBrowser.Api.Playback
mediaSource.TranscodingContainer = streamInfo.Container;
mediaSource.TranscodingSubProtocol = streamInfo.SubProtocol;
- }
- // Do this after the above so that StartPositionTicks is set
- SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token);
+ // Do this after the above so that StartPositionTicks is set
+ SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token);
+ }
}
}
diff --git a/MediaBrowser.Controller/Library/IMediaSourceProvider.cs b/MediaBrowser.Controller/Library/IMediaSourceProvider.cs
index 9e74879fc..ec7798551 100644
--- a/MediaBrowser.Controller/Library/IMediaSourceProvider.cs
+++ b/MediaBrowser.Controller/Library/IMediaSourceProvider.cs
@@ -1,3 +1,6 @@
+#pragma warning disable CS1591
+#pragma warning disable SA1600
+
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
diff --git a/MediaBrowser.Model/Users/UserPolicy.cs b/MediaBrowser.Model/Users/UserPolicy.cs
index e5f66b34b..48056f3dc 100644
--- a/MediaBrowser.Model/Users/UserPolicy.cs
+++ b/MediaBrowser.Model/Users/UserPolicy.cs
@@ -47,6 +47,7 @@ namespace MediaBrowser.Model.Users
public bool EnableAudioPlaybackTranscoding { get; set; }
public bool EnableVideoPlaybackTranscoding { get; set; }
public bool EnablePlaybackRemuxing { get; set; }
+ public bool ForceRemoteSourceTranscoding { get; set; }
public bool EnableContentDeletion { get; set; }
public string[] EnableContentDeletionFromFolders { get; set; }
@@ -94,7 +95,7 @@ namespace MediaBrowser.Model.Users
EnableAudioPlaybackTranscoding = true;
EnableVideoPlaybackTranscoding = true;
EnablePlaybackRemuxing = true;
-
+ ForceRemoteSourceTranscoding = false;
EnableLiveTvManagement = true;
EnableLiveTvAccess = true;
diff --git a/jellyfin.ruleset b/jellyfin.ruleset
index 92b7a03fd..e4d283167 100644
--- a/jellyfin.ruleset
+++ b/jellyfin.ruleset
@@ -5,6 +5,8 @@
<Rule Id="SA1202" Action="Info" />
<!-- disable warning SA1204: Static members must appear before non-static members -->
<Rule Id="SA1204" Action="Info" />
+ <!-- disable warning SA1404: Code analysis suppression should have justification -->
+ <Rule Id="SA1404" Action="Info" />
<!-- disable warning SA1009: Closing parenthesis should be followed by a space. -->
<Rule Id="SA1009" Action="None" />
diff --git a/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs b/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs
index 5017fce4d..5e023bdb0 100644
--- a/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs
+++ b/tests/Jellyfin.Naming.Tests/TV/EpisodeNumberTests.cs
@@ -13,6 +13,65 @@ namespace Jellyfin.Naming.Tests.TV
[InlineData("The Daily Show/The Daily Show 25x22 - [WEBDL-720p][AAC 2.0][x264] Noah Baumbach-TBS.mkv", 22)]
[InlineData("Castle Rock 2x01 Que el rio siga su curso [WEB-DL HULU 1080p h264 Dual DD5.1 Subs].mkv", 1)]
[InlineData("After Life 1x06 Episodio 6 [WEB-DL NF 1080p h264 Dual DD 5.1 Sub].mkv", 6)]
+ [InlineData("Season 02/S02E03 blah.avi", 3)]
+ [InlineData("Season 2/02x03 - 02x04 - 02x15 - Ep Name.mp4", 3)]
+ [InlineData("Season 02/02x03 - x04 - x15 - Ep Name.mp4", 3)]
+ [InlineData("Season 1/01x02 blah.avi", 2)]
+ [InlineData("Season 1/S01x02 blah.avi", 2)]
+ [InlineData("Season 1/S01E02 blah.avi", 2)]
+ [InlineData("Season 2/Elementary - 02x03-04-15 - Ep Name.mp4", 3)]
+ [InlineData("Season 1/S01xE02 blah.avi", 2)]
+ [InlineData("Season 1/seriesname S01E02 blah.avi", 2)]
+ [InlineData("Season 2/Episode - 16.avi", 16)]
+ [InlineData("Season 2/Episode 16.avi", 16)]
+ [InlineData("Season 2/Episode 16 - Some Title.avi", 16)]
+ [InlineData("Season 2/16 Some Title.avi", 16)]
+ [InlineData("Season 2/16 - 12 Some Title.avi", 16)]
+ [InlineData("Season 2/7 - 12 Angry Men.avi", 7)]
+ [InlineData("Season 1/seriesname 01x02 blah.avi", 2)]
+ [InlineData("Season 25/The Simpsons.S25E09.Steal this episode.mp4", 9)]
+ [InlineData("Season 1/seriesname S01x02 blah.avi", 2)]
+ [InlineData("Season 2/Elementary - 02x03 - 02x04 - 02x15 - Ep Name.mp4", 3)]
+ [InlineData("Season 1/seriesname S01xE02 blah.avi", 2)]
+ [InlineData("Season 02/Elementary - 02x03 - x04 - x15 - Ep Name.mp4", 3)]
+ [InlineData("Season 02/Elementary - 02x03x04x15 - Ep Name.mp4", 3)]
+ [InlineData("Season 2/02x03-04-15 - Ep Name.mp4", 3)]
+ [InlineData("Season 02/02x03-E15 - Ep Name.mp4", 3)]
+ [InlineData("Season 02/Elementary - 02x03-E15 - Ep Name.mp4", 3)]
+ [InlineData("Season 1/Elementary - S01E23-E24-E26 - The Woman.mp4", 23)]
+ [InlineData("Season 2009/S2009E23-E24-E26 - The Woman.mp4", 23)]
+ [InlineData("Season 2009/2009x02 blah.avi", 2)]
+ [InlineData("Season 2009/S2009x02 blah.avi", 2)]
+ [InlineData("Season 2009/S2009E02 blah.avi", 2)]
+ [InlineData("Season 2009/seriesname 2009x02 blah.avi", 2)]
+ [InlineData("Season 2009/Elementary - 2009x03x04x15 - Ep Name.mp4", 3)]
+ [InlineData("Season 2009/2009x03x04x15 - Ep Name.mp4", 3)]
+ [InlineData("Season 2009/Elementary - 2009x03-E15 - Ep Name.mp4", 3)]
+ [InlineData("Season 2009/S2009xE02 blah.avi", 2)]
+ [InlineData("Season 2009/Elementary - S2009E23-E24-E26 - The Woman.mp4", 23)]
+ [InlineData("Season 2009/seriesname S2009xE02 blah.avi", 2)]
+ [InlineData("Season 2009/2009x03-E15 - Ep Name.mp4", 3)]
+ [InlineData("Season 2009/seriesname S2009E02 blah.avi", 2)]
+ [InlineData("Season 2009/2009x03 - 2009x04 - 2009x15 - Ep Name.mp4", 3)]
+ [InlineData("Season 2009/2009x03 - x04 - x15 - Ep Name.mp4", 3)]
+ [InlineData("Season 2009/seriesname S2009x02 blah.avi", 2)]
+ [InlineData("Season 2009/Elementary - 2009x03 - 2009x04 - 2009x15 - Ep Name.mp4", 3)]
+ [InlineData("Season 2009/Elementary - 2009x03-04-15 - Ep Name.mp4", 3)]
+ [InlineData("Season 2009/2009x03-04-15 - Ep Name.mp4", 3)]
+ [InlineData("Season 2009/Elementary - 2009x03 - x04 - x15 - Ep Name.mp4", 3)]
+ [InlineData("Season 1/02 - blah-02 a.avi", 2)]
+ [InlineData("Season 1/02 - blah.avi", 2)]
+ [InlineData("Season 2/02 - blah 14 blah.avi", 2)]
+ [InlineData("Season 2/02.avi", 2)]
+ [InlineData("Season 2/2. Infestation.avi", 2)]
+ [InlineData("The Wonder Years/The.Wonder.Years.S04.PDTV.x264-JCH/The Wonder Years s04e07 Christmas Party NTSC PDTV.avi", 7)]
+ [InlineData("Running Man/Running Man S2017E368.mkv", 368)]
+ // TODO: [InlineData("Season 2/16 12 Some Title.avi", 16)]
+ // TODO: [InlineData("/The.Legend.of.Condor.Heroes.2017.V2.web-dl.1080p.h264.aac-hdctv/The.Legend.of.Condor.Heroes.2017.E07.V2.web-dl.1080p.h264.aac-hdctv.mkv", 7)]
+ // TODO: [InlineData("Season 4/Uchuu.Senkan.Yamato.2199.E03.avi", 3)]
+ // TODO: [InlineData("Season 2/7 12 Angry Men.avi", 7)]
+ // TODO: [InlineData("Season 02/02x03x04x15 - Ep Name.mp4", 2)]
+ // TODO: [InlineData("Season 2/[HorribleSubs] Hunter X Hunter - 136 [720p].mkv", 136)]
public void GetEpisodeNumberFromFileTest(string path, int? expected)
{
var result = new EpisodePathParser(_namingOptions)
@@ -20,387 +79,5 @@ namespace Jellyfin.Naming.Tests.TV
Assert.Equal(expected, result.EpisodeNumber);
}
-
- [Fact]
- public void TestEpisodeNumber1()
- {
- Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 02/S02E03 blah.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber40()
- {
- Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2/02x03 - 02x04 - 02x15 - Ep Name.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber41()
- {
- Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 1/01x02 blah.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber42()
- {
- Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 1/S01x02 blah.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber43()
- {
- Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 1/S01E02 blah.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber44()
- {
- Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2/Elementary - 02x03-04-15 - Ep Name.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber45()
- {
- Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 1/S01xE02 blah.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber46()
- {
- Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 1/seriesname S01E02 blah.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber47()
- {
- Assert.Equal(36, GetEpisodeNumberFromFile(@"Season 2/[HorribleSubs] Hunter X Hunter - 136 [720p].mkv"));
- }
-
- [Fact]
- public void TestEpisodeNumber52()
- {
- Assert.Equal(16, GetEpisodeNumberFromFile(@"Season 2/Episode - 16.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber53()
- {
- Assert.Equal(16, GetEpisodeNumberFromFile(@"Season 2/Episode 16.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber54()
- {
- Assert.Equal(16, GetEpisodeNumberFromFile(@"Season 2/Episode 16 - Some Title.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber57()
- {
- Assert.Equal(16, GetEpisodeNumberFromFile(@"Season 2/16 Some Title.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber58()
- {
- Assert.Equal(16, GetEpisodeNumberFromFile(@"Season 2/16 - 12 Some Title.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber59()
- {
- Assert.Equal(7, GetEpisodeNumberFromFile(@"Season 2/7 - 12 Angry Men.avi"));
- }
-
- // FIXME
- // [Fact]
- public void TestEpisodeNumber60()
- {
- Assert.Equal(16, GetEpisodeNumberFromFile(@"Season 2/16 12 Some Title.avi"));
- }
-
- // FIXME
- // [Fact]
- public void TestEpisodeNumber61()
- {
- Assert.Equal(7, GetEpisodeNumberFromFile(@"Season 2/7 12 Angry Men.avi"));
- }
-
- // FIXME
- // [Fact]
- public void TestEpisodeNumber62()
- {
- // This is not supported. Expected to fail, although it would be a good one to add support for.
- Assert.Equal(3, GetEpisodeNumberFromFile(@"Season 4/Uchuu.Senkan.Yamato.2199.E03.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber63()
- {
- Assert.Equal(3, GetEpisodeNumberFromFile(@"Season 4/Uchuu.Senkan.Yamato.2199.S04E03.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber64()
- {
- Assert.Equal(368, GetEpisodeNumberFromFile(@"Running Man/Running Man S2017E368.mkv"));
- }
-
- // FIXME
- // [Fact]
- public void TestEpisodeNumber65()
- {
- // Not supported yet
- Assert.Equal(7, GetEpisodeNumberFromFile(@"/The.Legend.of.Condor.Heroes.2017.V2.web-dl.1080p.h264.aac-hdctv/The.Legend.of.Condor.Heroes.2017.E07.V2.web-dl.1080p.h264.aac-hdctv.mkv"));
- }
-
- [Fact]
- public void TestEpisodeNumber30()
- {
- Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2/02x03 - 02x04 - 02x15 - Ep Name.mp4"));
- }
-
- // FIXME
- // [Fact]
- public void TestEpisodeNumber31()
- {
- Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 1/seriesname 01x02 blah.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber32()
- {
- Assert.Equal(9, GetEpisodeNumberFromFile(@"Season 25/The Simpsons.S25E09.Steal this episode.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber33()
- {
- Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 1/seriesname S01x02 blah.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber34()
- {
- Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2/Elementary - 02x03 - 02x04 - 02x15 - Ep Name.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber35()
- {
- Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 1/seriesname S01xE02 blah.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber36()
- {
- Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 02/02x03 - x04 - x15 - Ep Name.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber37()
- {
- Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 02/Elementary - 02x03 - x04 - x15 - Ep Name.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber38()
- {
- Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 02/02x03x04x15 - Ep Name.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber39()
- {
- Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 02/Elementary - 02x03x04x15 - Ep Name.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber20()
- {
- Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2/02x03-04-15 - Ep Name.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber21()
- {
- Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 02/02x03-E15 - Ep Name.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber22()
- {
- Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 02/Elementary - 02x03-E15 - Ep Name.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber23()
- {
- Assert.Equal(23, GetEpisodeNumberFromFile(@"Season 1/Elementary - S01E23-E24-E26 - The Woman.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber24()
- {
- Assert.Equal(23, GetEpisodeNumberFromFile(@"Season 2009/S2009E23-E24-E26 - The Woman.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber25()
- {
- Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 2009/2009x02 blah.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber26()
- {
- Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 2009/S2009x02 blah.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber27()
- {
- Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 2009/S2009E02 blah.avi"));
- }
-
- // FIXME
- // [Fact]
- public void TestEpisodeNumber28()
- {
- Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 2009/seriesname 2009x02 blah.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber29()
- {
- Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2009/Elementary - 2009x03x04x15 - Ep Name.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber11()
- {
- Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2009/2009x03x04x15 - Ep Name.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber12()
- {
- Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2009/Elementary - 2009x03-E15 - Ep Name.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber13()
- {
- Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 2009/S2009xE02 blah.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber14()
- {
- Assert.Equal(23, GetEpisodeNumberFromFile(@"Season 2009/Elementary - S2009E23-E24-E26 - The Woman.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber15()
- {
- Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 2009/seriesname S2009xE02 blah.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber16()
- {
- Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2009/2009x03-E15 - Ep Name.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber17()
- {
- Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 2009/seriesname S2009E02 blah.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber18()
- {
- Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2009/2009x03 - 2009x04 - 2009x15 - Ep Name.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber19()
- {
- Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2009/2009x03 - x04 - x15 - Ep Name.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber2()
- {
- Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 2009/seriesname S2009x02 blah.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber3()
- {
- Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2009/Elementary - 2009x03 - 2009x04 - 2009x15 - Ep Name.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber4()
- {
- Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2009/Elementary - 2009x03-04-15 - Ep Name.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber5()
- {
- Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2009/2009x03-04-15 - Ep Name.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber6()
- {
- Assert.Equal(03, GetEpisodeNumberFromFile(@"Season 2009/Elementary - 2009x03 - x04 - x15 - Ep Name.mp4"));
- }
-
- [Fact]
- public void TestEpisodeNumber7()
- {
- Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 1/02 - blah-02 a.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber8()
- {
- Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 1/02 - blah.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber9()
- {
- Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 2/02 - blah 14 blah.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber10()
- {
- Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 2/02.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber48()
- {
- Assert.Equal(02, GetEpisodeNumberFromFile(@"Season 2/2. Infestation.avi"));
- }
-
- [Fact]
- public void TestEpisodeNumber49()
- {
- Assert.Equal(7, GetEpisodeNumberFromFile(@"The Wonder Years/The.Wonder.Years.S04.PDTV.x264-JCH/The Wonder Years s04e07 Christmas Party NTSC PDTV.avi"));
- }
-
- private int? GetEpisodeNumberFromFile(string path)
- {
- var result = new EpisodePathParser(_namingOptions)
- .Parse(path, false);
-
- return result.EpisodeNumber;
- }
}
}