Browse Source

Merge pull request #3939 from Bond-009/warn24

Make MediaBrowser.MediaEncoding warnings free
Anthony Lavado 4 years ago
parent
commit
ac58d07e0e

+ 3 - 3
Emby.Dlna/Main/DlnaEntryPoint.cs

@@ -30,10 +30,8 @@ using OperatingSystem = MediaBrowser.Common.System.OperatingSystem;
 
 
 namespace Emby.Dlna.Main
 namespace Emby.Dlna.Main
 {
 {
-    public class DlnaEntryPoint : IServerEntryPoint, IRunBeforeStartup
+    public sealed class DlnaEntryPoint : IServerEntryPoint, IRunBeforeStartup
     {
     {
-        public static DlnaEntryPoint Current;
-
         private readonly IServerConfigurationManager _config;
         private readonly IServerConfigurationManager _config;
         private readonly ILogger<DlnaEntryPoint> _logger;
         private readonly ILogger<DlnaEntryPoint> _logger;
         private readonly IServerApplicationHost _appHost;
         private readonly IServerApplicationHost _appHost;
@@ -122,6 +120,8 @@ namespace Emby.Dlna.Main
                 config);
                 config);
             Current = this;
             Current = this;
         }
         }
+        
+        public static DlnaEntryPoint Current { get; private set; }
 
 
         public IContentDirectory ContentDirectory { get; private set; }
         public IContentDirectory ContentDirectory { get; private set; }
 
 

+ 1 - 1
Emby.Dlna/PlayTo/uBaseObject.cs

@@ -56,7 +56,7 @@ namespace Emby.Dlna.PlayTo
                 throw new ArgumentNullException(nameof(obj));
                 throw new ArgumentNullException(nameof(obj));
             }
             }
 
 
-            return string.Equals(Id, obj.Id, StringComparison.InvariantCulture);
+            return string.Equals(Id, obj.Id, StringComparison.Ordinal);
         }
         }
     }
     }
 }
 }

+ 1 - 1
Emby.Dlna/PlayTo/uPnpNamespaces.cs

@@ -4,7 +4,7 @@ using System.Xml.Linq;
 
 
 namespace Emby.Dlna.PlayTo
 namespace Emby.Dlna.PlayTo
 {
 {
-    public class uPnpNamespaces
+    public static class uPnpNamespaces
     {
     {
         public static XNamespace dc = "http://purl.org/dc/elements/1.1/";
         public static XNamespace dc = "http://purl.org/dc/elements/1.1/";
         public static XNamespace ns = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/";
         public static XNamespace ns = "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/";

+ 5 - 2
Emby.Server.Implementations/Data/SqliteItemRepository.cs

@@ -4308,7 +4308,7 @@ namespace Emby.Server.Implementations.Data
                 whereClauses.Add("ProductionYear=@Years");
                 whereClauses.Add("ProductionYear=@Years");
                 if (statement != null)
                 if (statement != null)
                 {
                 {
-                    statement.TryBind("@Years", query.Years[0].ToString());
+                    statement.TryBind("@Years", query.Years[0].ToString(CultureInfo.InvariantCulture));
                 }
                 }
             }
             }
             else if (query.Years.Length > 1)
             else if (query.Years.Length > 1)
@@ -5170,7 +5170,10 @@ where AncestorIdText not null and ItemValues.Value not null and ItemValues.Type
                     insertText.Append(',');
                     insertText.Append(',');
                 }
                 }
 
 
-                insertText.AppendFormat("(@ItemId, @AncestorId{0}, @AncestorIdText{0})", i.ToString(CultureInfo.InvariantCulture));
+                insertText.AppendFormat(
+                    CultureInfo.InvariantCulture,
+                    "(@ItemId, @AncestorId{0}, @AncestorIdText{0})",
+                    i.ToString(CultureInfo.InvariantCulture));
             }
             }
 
 
             using (var statement = PrepareStatement(db, insertText.ToString()))
             using (var statement = PrepareStatement(db, insertText.ToString()))

+ 3 - 24
Emby.Server.Implementations/IO/LibraryMonitor.cs

@@ -6,12 +6,11 @@ using System.Collections.Generic;
 using System.IO;
 using System.IO;
 using System.Linq;
 using System.Linq;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
+using Emby.Server.Implementations.Library;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Plugins;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.IO;
-using Emby.Server.Implementations.Library;
 using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.Logging;
 
 
 namespace Emby.Server.Implementations.IO
 namespace Emby.Server.Implementations.IO
@@ -38,6 +37,8 @@ namespace Emby.Server.Implementations.IO
         /// </summary>
         /// </summary>
         private readonly ConcurrentDictionary<string, string> _tempIgnoredPaths = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
         private readonly ConcurrentDictionary<string, string> _tempIgnoredPaths = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
 
 
+        private bool _disposed = false;
+
         /// <summary>
         /// <summary>
         /// Add the path to our temporary ignore list.  Use when writing to a path within our listening scope.
         /// Add the path to our temporary ignore list.  Use when writing to a path within our listening scope.
         /// </summary>
         /// </summary>
@@ -492,8 +493,6 @@ namespace Emby.Server.Implementations.IO
             }
             }
         }
         }
 
 
-        private bool _disposed = false;
-
         /// <summary>
         /// <summary>
         /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
         /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
         /// </summary>
         /// </summary>
@@ -522,24 +521,4 @@ namespace Emby.Server.Implementations.IO
             _disposed = true;
             _disposed = true;
         }
         }
     }
     }
-
-    public class LibraryMonitorStartup : IServerEntryPoint
-    {
-        private readonly ILibraryMonitor _monitor;
-
-        public LibraryMonitorStartup(ILibraryMonitor monitor)
-        {
-            _monitor = monitor;
-        }
-
-        public Task RunAsync()
-        {
-            _monitor.Start();
-            return Task.CompletedTask;
-        }
-
-        public void Dispose()
-        {
-        }
-    }
 }
 }

+ 35 - 0
Emby.Server.Implementations/IO/LibraryMonitorStartup.cs

@@ -0,0 +1,35 @@
+using System.Threading.Tasks;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Plugins;
+
+namespace Emby.Server.Implementations.IO
+{
+    /// <summary>
+    /// <see cref="IServerEntryPoint" /> which is responsible for starting the library monitor.
+    /// </summary>
+    public sealed class LibraryMonitorStartup : IServerEntryPoint
+    {
+        private readonly ILibraryMonitor _monitor;
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="LibraryMonitorStartup"/> class.
+        /// </summary>
+        /// <param name="monitor">The library monitor.</param>
+        public LibraryMonitorStartup(ILibraryMonitor monitor)
+        {
+            _monitor = monitor;
+        }
+
+        /// <inheritdoc />
+        public Task RunAsync()
+        {
+            _monitor.Start();
+            return Task.CompletedTask;
+        }
+
+        /// <inheritdoc />
+        public void Dispose()
+        {
+        }
+    }
+}

+ 1 - 1
Emby.Server.Implementations/Library/LibraryManager.cs

@@ -729,7 +729,7 @@ namespace Emby.Server.Implementations.Library
             Directory.CreateDirectory(rootFolderPath);
             Directory.CreateDirectory(rootFolderPath);
 
 
             var rootFolder = GetItemById(GetNewItemId(rootFolderPath, typeof(AggregateFolder))) as AggregateFolder ??
             var rootFolder = GetItemById(GetNewItemId(rootFolderPath, typeof(AggregateFolder))) as AggregateFolder ??
-                             ((Folder) ResolvePath(_fileSystem.GetDirectoryInfo(rootFolderPath)))
+                             ((Folder)ResolvePath(_fileSystem.GetDirectoryInfo(rootFolderPath)))
                              .DeepCopy<Folder, AggregateFolder>();
                              .DeepCopy<Folder, AggregateFolder>();
 
 
             // In case program data folder was moved
             // In case program data folder was moved

+ 1 - 1
Emby.Server.Implementations/LiveTv/EmbyTV/EntryPoint.cs

@@ -5,7 +5,7 @@ using MediaBrowser.Controller.Plugins;
 
 
 namespace Emby.Server.Implementations.LiveTv.EmbyTV
 namespace Emby.Server.Implementations.LiveTv.EmbyTV
 {
 {
-    public class EntryPoint : IServerEntryPoint
+    public sealed class EntryPoint : IServerEntryPoint
     {
     {
         /// <inheritdoc />
         /// <inheritdoc />
         public Task RunAsync()
         public Task RunAsync()

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

@@ -929,7 +929,7 @@ namespace Emby.Server.Implementations.LiveTv.Listings
 
 
         private static string NormalizeName(string value)
         private static string NormalizeName(string value)
         {
         {
-            return value.Replace(" ", string.Empty).Replace("-", string.Empty);
+            return value.Replace(" ", string.Empty, StringComparison.Ordinal).Replace("-", string.Empty, StringComparison.Ordinal);
         }
         }
 
 
         public class ScheduleDirect
         public class ScheduleDirect

+ 75 - 73
Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs

@@ -10,7 +10,6 @@ using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Common.Progress;
 using MediaBrowser.Common.Progress;
 using MediaBrowser.Model.Events;
 using MediaBrowser.Model.Events;
-using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Serialization;
 using MediaBrowser.Model.Serialization;
 using MediaBrowser.Model.Tasks;
 using MediaBrowser.Model.Tasks;
 using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.Logging;
@@ -22,37 +21,53 @@ namespace Emby.Server.Implementations.ScheduledTasks
     /// </summary>
     /// </summary>
     public class ScheduledTaskWorker : IScheduledTaskWorker
     public class ScheduledTaskWorker : IScheduledTaskWorker
     {
     {
-        public event EventHandler<GenericEventArgs<double>> TaskProgress;
-
-        /// <summary>
-        /// Gets the scheduled task.
-        /// </summary>
-        /// <value>The scheduled task.</value>
-        public IScheduledTask ScheduledTask { get; private set; }
-
         /// <summary>
         /// <summary>
         /// Gets or sets the json serializer.
         /// Gets or sets the json serializer.
         /// </summary>
         /// </summary>
         /// <value>The json serializer.</value>
         /// <value>The json serializer.</value>
-        private IJsonSerializer JsonSerializer { get; set; }
+        private readonly IJsonSerializer _jsonSerializer;
 
 
         /// <summary>
         /// <summary>
         /// Gets or sets the application paths.
         /// Gets or sets the application paths.
         /// </summary>
         /// </summary>
         /// <value>The application paths.</value>
         /// <value>The application paths.</value>
-        private IApplicationPaths ApplicationPaths { get; set; }
+        private readonly IApplicationPaths _applicationPaths;
 
 
         /// <summary>
         /// <summary>
-        /// Gets the logger.
+        /// Gets or sets the logger.
         /// </summary>
         /// </summary>
         /// <value>The logger.</value>
         /// <value>The logger.</value>
-        private ILogger Logger { get; set; }
+        private readonly ILogger _logger;
 
 
         /// <summary>
         /// <summary>
-        /// Gets the task manager.
+        /// Gets or sets the task manager.
         /// </summary>
         /// </summary>
         /// <value>The task manager.</value>
         /// <value>The task manager.</value>
-        private ITaskManager TaskManager { get; set; }
+        private readonly ITaskManager _taskManager;
+
+        /// <summary>
+        /// The _last execution result sync lock.
+        /// </summary>
+        private readonly object _lastExecutionResultSyncLock = new object();
+
+        private bool _readFromFile = false;
+
+        /// <summary>
+        /// The _last execution result.
+        /// </summary>
+        private TaskResult _lastExecutionResult;
+
+        private Task _currentTask;
+
+        /// <summary>
+        /// The _triggers.
+        /// </summary>
+        private Tuple<TaskTriggerInfo, ITaskTrigger>[] _triggers;
+
+        /// <summary>
+        /// The _id.
+        /// </summary>
+        private string _id;
 
 
         /// <summary>
         /// <summary>
         /// Initializes a new instance of the <see cref="ScheduledTaskWorker" /> class.
         /// Initializes a new instance of the <see cref="ScheduledTaskWorker" /> class.
@@ -71,7 +86,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
         /// or
         /// or
         /// jsonSerializer
         /// jsonSerializer
         /// or
         /// or
-        /// logger
+        /// logger.
         /// </exception>
         /// </exception>
         public ScheduledTaskWorker(IScheduledTask scheduledTask, IApplicationPaths applicationPaths, ITaskManager taskManager, IJsonSerializer jsonSerializer, ILogger logger)
         public ScheduledTaskWorker(IScheduledTask scheduledTask, IApplicationPaths applicationPaths, ITaskManager taskManager, IJsonSerializer jsonSerializer, ILogger logger)
         {
         {
@@ -101,23 +116,22 @@ namespace Emby.Server.Implementations.ScheduledTasks
             }
             }
 
 
             ScheduledTask = scheduledTask;
             ScheduledTask = scheduledTask;
-            ApplicationPaths = applicationPaths;
-            TaskManager = taskManager;
-            JsonSerializer = jsonSerializer;
-            Logger = logger;
+            _applicationPaths = applicationPaths;
+            _taskManager = taskManager;
+            _jsonSerializer = jsonSerializer;
+            _logger = logger;
 
 
             InitTriggerEvents();
             InitTriggerEvents();
         }
         }
 
 
-        private bool _readFromFile = false;
-        /// <summary>
-        /// The _last execution result.
-        /// </summary>
-        private TaskResult _lastExecutionResult;
+        public event EventHandler<GenericEventArgs<double>> TaskProgress;
+
         /// <summary>
         /// <summary>
-        /// The _last execution result sync lock.
+        /// Gets the scheduled task.
         /// </summary>
         /// </summary>
-        private readonly object _lastExecutionResultSyncLock = new object();
+        /// <value>The scheduled task.</value>
+        public IScheduledTask ScheduledTask { get; private set; }
+
         /// <summary>
         /// <summary>
         /// Gets the last execution result.
         /// Gets the last execution result.
         /// </summary>
         /// </summary>
@@ -136,11 +150,11 @@ namespace Emby.Server.Implementations.ScheduledTasks
                         {
                         {
                             try
                             try
                             {
                             {
-                                _lastExecutionResult = JsonSerializer.DeserializeFromFile<TaskResult>(path);
+                                _lastExecutionResult = _jsonSerializer.DeserializeFromFile<TaskResult>(path);
                             }
                             }
                             catch (Exception ex)
                             catch (Exception ex)
                             {
                             {
-                                Logger.LogError(ex, "Error deserializing {File}", path);
+                                _logger.LogError(ex, "Error deserializing {File}", path);
                             }
                             }
                         }
                         }
 
 
@@ -160,7 +174,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
 
 
                 lock (_lastExecutionResultSyncLock)
                 lock (_lastExecutionResultSyncLock)
                 {
                 {
-                    JsonSerializer.SerializeToFile(value, path);
+                    _jsonSerializer.SerializeToFile(value, path);
                 }
                 }
             }
             }
         }
         }
@@ -184,7 +198,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
         public string Category => ScheduledTask.Category;
         public string Category => ScheduledTask.Category;
 
 
         /// <summary>
         /// <summary>
-        /// Gets the current cancellation token.
+        /// Gets or sets the current cancellation token.
         /// </summary>
         /// </summary>
         /// <value>The current cancellation token source.</value>
         /// <value>The current cancellation token source.</value>
         private CancellationTokenSource CurrentCancellationTokenSource { get; set; }
         private CancellationTokenSource CurrentCancellationTokenSource { get; set; }
@@ -221,12 +235,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
         public double? CurrentProgress { get; private set; }
         public double? CurrentProgress { get; private set; }
 
 
         /// <summary>
         /// <summary>
-        /// The _triggers.
-        /// </summary>
-        private Tuple<TaskTriggerInfo, ITaskTrigger>[] _triggers;
-
-        /// <summary>
-        /// Gets the triggers that define when the task will run.
+        /// Gets or sets the triggers that define when the task will run.
         /// </summary>
         /// </summary>
         /// <value>The triggers.</value>
         /// <value>The triggers.</value>
         private Tuple<TaskTriggerInfo, ITaskTrigger>[] InternalTriggers
         private Tuple<TaskTriggerInfo, ITaskTrigger>[] InternalTriggers
@@ -255,7 +264,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
         /// Gets the triggers that define when the task will run.
         /// Gets the triggers that define when the task will run.
         /// </summary>
         /// </summary>
         /// <value>The triggers.</value>
         /// <value>The triggers.</value>
-        /// <exception cref="ArgumentNullException">value</exception>
+        /// <exception cref="ArgumentNullException"><c>value</c> is <c>null</c>.</exception>
         public TaskTriggerInfo[] Triggers
         public TaskTriggerInfo[] Triggers
         {
         {
             get
             get
@@ -280,11 +289,6 @@ namespace Emby.Server.Implementations.ScheduledTasks
             }
             }
         }
         }
 
 
-        /// <summary>
-        /// The _id.
-        /// </summary>
-        private string _id;
-
         /// <summary>
         /// <summary>
         /// Gets the unique id.
         /// Gets the unique id.
         /// </summary>
         /// </summary>
@@ -325,9 +329,9 @@ namespace Emby.Server.Implementations.ScheduledTasks
 
 
                 trigger.Stop();
                 trigger.Stop();
 
 
-                trigger.Triggered -= trigger_Triggered;
-                trigger.Triggered += trigger_Triggered;
-                trigger.Start(LastExecutionResult, Logger, Name, isApplicationStartup);
+                trigger.Triggered -= OnTriggerTriggered;
+                trigger.Triggered += OnTriggerTriggered;
+                trigger.Start(LastExecutionResult, _logger, Name, isApplicationStartup);
             }
             }
         }
         }
 
 
@@ -336,7 +340,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
         /// </summary>
         /// </summary>
         /// <param name="sender">The source of the event.</param>
         /// <param name="sender">The source of the event.</param>
         /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
         /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param>
-        async void trigger_Triggered(object sender, EventArgs e)
+        private async void OnTriggerTriggered(object sender, EventArgs e)
         {
         {
             var trigger = (ITaskTrigger)sender;
             var trigger = (ITaskTrigger)sender;
 
 
@@ -347,19 +351,17 @@ namespace Emby.Server.Implementations.ScheduledTasks
                 return;
                 return;
             }
             }
 
 
-            Logger.LogInformation("{0} fired for task: {1}", trigger.GetType().Name, Name);
+            _logger.LogInformation("{0} fired for task: {1}", trigger.GetType().Name, Name);
 
 
             trigger.Stop();
             trigger.Stop();
 
 
-            TaskManager.QueueScheduledTask(ScheduledTask, trigger.TaskOptions);
+            _taskManager.QueueScheduledTask(ScheduledTask, trigger.TaskOptions);
 
 
             await Task.Delay(1000).ConfigureAwait(false);
             await Task.Delay(1000).ConfigureAwait(false);
 
 
-            trigger.Start(LastExecutionResult, Logger, Name, false);
+            trigger.Start(LastExecutionResult, _logger, Name, false);
         }
         }
 
 
-        private Task _currentTask;
-
         /// <summary>
         /// <summary>
         /// Executes the task.
         /// Executes the task.
         /// </summary>
         /// </summary>
@@ -395,9 +397,9 @@ namespace Emby.Server.Implementations.ScheduledTasks
 
 
             CurrentCancellationTokenSource = new CancellationTokenSource();
             CurrentCancellationTokenSource = new CancellationTokenSource();
 
 
-            Logger.LogInformation("Executing {0}", Name);
+            _logger.LogInformation("Executing {0}", Name);
 
 
-            ((TaskManager)TaskManager).OnTaskExecuting(this);
+            ((TaskManager)_taskManager).OnTaskExecuting(this);
 
 
             progress.ProgressChanged += OnProgressChanged;
             progress.ProgressChanged += OnProgressChanged;
 
 
@@ -423,7 +425,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
             }
             }
             catch (Exception ex)
             catch (Exception ex)
             {
             {
-                Logger.LogError(ex, "Error");
+                _logger.LogError(ex, "Error");
 
 
                 failureException = ex;
                 failureException = ex;
 
 
@@ -476,7 +478,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
         {
         {
             if (State == TaskState.Running)
             if (State == TaskState.Running)
             {
             {
-                Logger.LogInformation("Attempting to cancel Scheduled Task {0}", Name);
+                _logger.LogInformation("Attempting to cancel Scheduled Task {0}", Name);
                 CurrentCancellationTokenSource.Cancel();
                 CurrentCancellationTokenSource.Cancel();
             }
             }
         }
         }
@@ -487,7 +489,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
         /// <returns>System.String.</returns>
         /// <returns>System.String.</returns>
         private string GetScheduledTasksConfigurationDirectory()
         private string GetScheduledTasksConfigurationDirectory()
         {
         {
-            return Path.Combine(ApplicationPaths.ConfigurationDirectoryPath, "ScheduledTasks");
+            return Path.Combine(_applicationPaths.ConfigurationDirectoryPath, "ScheduledTasks");
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -496,7 +498,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
         /// <returns>System.String.</returns>
         /// <returns>System.String.</returns>
         private string GetScheduledTasksDataDirectory()
         private string GetScheduledTasksDataDirectory()
         {
         {
-            return Path.Combine(ApplicationPaths.DataPath, "ScheduledTasks");
+            return Path.Combine(_applicationPaths.DataPath, "ScheduledTasks");
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -535,7 +537,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
             TaskTriggerInfo[] list = null;
             TaskTriggerInfo[] list = null;
             if (File.Exists(path))
             if (File.Exists(path))
             {
             {
-                list = JsonSerializer.DeserializeFromFile<TaskTriggerInfo[]>(path);
+                list = _jsonSerializer.DeserializeFromFile<TaskTriggerInfo[]>(path);
             }
             }
 
 
             // Return defaults if file doesn't exist.
             // Return defaults if file doesn't exist.
@@ -571,7 +573,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
 
 
             Directory.CreateDirectory(Path.GetDirectoryName(path));
             Directory.CreateDirectory(Path.GetDirectoryName(path));
 
 
-            JsonSerializer.SerializeToFile(triggers, path);
+            _jsonSerializer.SerializeToFile(triggers, path);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -585,7 +587,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
         {
         {
             var elapsedTime = endTime - startTime;
             var elapsedTime = endTime - startTime;
 
 
-            Logger.LogInformation("{0} {1} after {2} minute(s) and {3} seconds", Name, status, Math.Truncate(elapsedTime.TotalMinutes), elapsedTime.Seconds);
+            _logger.LogInformation("{0} {1} after {2} minute(s) and {3} seconds", Name, status, Math.Truncate(elapsedTime.TotalMinutes), elapsedTime.Seconds);
 
 
             var result = new TaskResult
             var result = new TaskResult
             {
             {
@@ -606,7 +608,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
 
 
             LastExecutionResult = result;
             LastExecutionResult = result;
 
 
-            ((TaskManager)TaskManager).OnTaskCompleted(this, result);
+            ((TaskManager)_taskManager).OnTaskCompleted(this, result);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -615,6 +617,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
         public void Dispose()
         public void Dispose()
         {
         {
             Dispose(true);
             Dispose(true);
+            GC.SuppressFinalize(this);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -635,12 +638,12 @@ namespace Emby.Server.Implementations.ScheduledTasks
                 {
                 {
                     try
                     try
                     {
                     {
-                        Logger.LogInformation(Name + ": Cancelling");
+                        _logger.LogInformation(Name + ": Cancelling");
                         token.Cancel();
                         token.Cancel();
                     }
                     }
                     catch (Exception ex)
                     catch (Exception ex)
                     {
                     {
-                        Logger.LogError(ex, "Error calling CancellationToken.Cancel();");
+                        _logger.LogError(ex, "Error calling CancellationToken.Cancel();");
                     }
                     }
                 }
                 }
 
 
@@ -649,21 +652,21 @@ namespace Emby.Server.Implementations.ScheduledTasks
                 {
                 {
                     try
                     try
                     {
                     {
-                        Logger.LogInformation(Name + ": Waiting on Task");
+                        _logger.LogInformation(Name + ": Waiting on Task");
                         var exited = Task.WaitAll(new[] { task }, 2000);
                         var exited = Task.WaitAll(new[] { task }, 2000);
 
 
                         if (exited)
                         if (exited)
                         {
                         {
-                            Logger.LogInformation(Name + ": Task exited");
+                            _logger.LogInformation(Name + ": Task exited");
                         }
                         }
                         else
                         else
                         {
                         {
-                            Logger.LogInformation(Name + ": Timed out waiting for task to stop");
+                            _logger.LogInformation(Name + ": Timed out waiting for task to stop");
                         }
                         }
                     }
                     }
                     catch (Exception ex)
                     catch (Exception ex)
                     {
                     {
-                        Logger.LogError(ex, "Error calling Task.WaitAll();");
+                        _logger.LogError(ex, "Error calling Task.WaitAll();");
                     }
                     }
                 }
                 }
 
 
@@ -671,12 +674,12 @@ namespace Emby.Server.Implementations.ScheduledTasks
                 {
                 {
                     try
                     try
                     {
                     {
-                        Logger.LogDebug(Name + ": Disposing CancellationToken");
+                        _logger.LogDebug(Name + ": Disposing CancellationToken");
                         token.Dispose();
                         token.Dispose();
                     }
                     }
                     catch (Exception ex)
                     catch (Exception ex)
                     {
                     {
-                        Logger.LogError(ex, "Error calling CancellationToken.Dispose();");
+                        _logger.LogError(ex, "Error calling CancellationToken.Dispose();");
                     }
                     }
                 }
                 }
 
 
@@ -692,8 +695,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
         /// </summary>
         /// </summary>
         /// <param name="info">The info.</param>
         /// <param name="info">The info.</param>
         /// <returns>BaseTaskTrigger.</returns>
         /// <returns>BaseTaskTrigger.</returns>
-        /// <exception cref="ArgumentNullException"></exception>
-        /// <exception cref="ArgumentException">Invalid trigger type:  + info.Type</exception>
+        /// <exception cref="ArgumentException">Invalid trigger type:  + info.Type.</exception>
         private ITaskTrigger GetTrigger(TaskTriggerInfo info)
         private ITaskTrigger GetTrigger(TaskTriggerInfo info)
         {
         {
             var options = new TaskOptions
             var options = new TaskOptions
@@ -765,7 +767,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
             foreach (var triggerInfo in InternalTriggers)
             foreach (var triggerInfo in InternalTriggers)
             {
             {
                 var trigger = triggerInfo.Item2;
                 var trigger = triggerInfo.Item2;
-                trigger.Triggered -= trigger_Triggered;
+                trigger.Triggered -= OnTriggerTriggered;
                 trigger.Stop();
                 trigger.Stop();
             }
             }
         }
         }

+ 1 - 0
Emby.Server.Implementations/ScheduledTasks/TaskManager.cs

@@ -207,6 +207,7 @@ namespace Emby.Server.Implementations.ScheduledTasks
         public void Dispose()
         public void Dispose()
         {
         {
             Dispose(true);
             Dispose(true);
+            GC.SuppressFinalize(this);
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 32 - 32
Emby.Server.Implementations/ScheduledTasks/Tasks/DeleteLogFileTask.cs

@@ -1,12 +1,13 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.Globalization;
 using System.Linq;
 using System.Linq;
 using System.Threading;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Configuration;
+using MediaBrowser.Model.Globalization;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Tasks;
 using MediaBrowser.Model.Tasks;
-using MediaBrowser.Model.Globalization;
 
 
 namespace Emby.Server.Implementations.ScheduledTasks.Tasks
 namespace Emby.Server.Implementations.ScheduledTasks.Tasks
 {
 {
@@ -15,12 +16,7 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
     /// </summary>
     /// </summary>
     public class DeleteLogFileTask : IScheduledTask, IConfigurableScheduledTask
     public class DeleteLogFileTask : IScheduledTask, IConfigurableScheduledTask
     {
     {
-        /// <summary>
-        /// Gets or sets the configuration manager.
-        /// </summary>
-        /// <value>The configuration manager.</value>
-        private IConfigurationManager ConfigurationManager { get; set; }
-
+        private readonly IConfigurationManager _configurationManager;
         private readonly IFileSystem _fileSystem;
         private readonly IFileSystem _fileSystem;
         private readonly ILocalizationManager _localization;
         private readonly ILocalizationManager _localization;
 
 
@@ -32,18 +28,43 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
         /// <param name="localization">The localization manager.</param>
         /// <param name="localization">The localization manager.</param>
         public DeleteLogFileTask(IConfigurationManager configurationManager, IFileSystem fileSystem, ILocalizationManager localization)
         public DeleteLogFileTask(IConfigurationManager configurationManager, IFileSystem fileSystem, ILocalizationManager localization)
         {
         {
-            ConfigurationManager = configurationManager;
+            _configurationManager = configurationManager;
             _fileSystem = fileSystem;
             _fileSystem = fileSystem;
             _localization = localization;
             _localization = localization;
         }
         }
 
 
+        /// <inheritdoc />
+        public string Name => _localization.GetLocalizedString("TaskCleanLogs");
+
+        /// <inheritdoc />
+        public string Description => string.Format(
+            CultureInfo.InvariantCulture,
+            _localization.GetLocalizedString("TaskCleanLogsDescription"),
+            _configurationManager.CommonConfiguration.LogFileRetentionDays);
+
+        /// <inheritdoc />
+        public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
+
+        /// <inheritdoc />
+        public string Key => "CleanLogFiles";
+
+        /// <inheritdoc />
+        public bool IsHidden => false;
+
+        /// <inheritdoc />
+        public bool IsEnabled => true;
+
+        /// <inheritdoc />
+        public bool IsLogged => true;
+
         /// <summary>
         /// <summary>
         /// Creates the triggers that define when the task will run.
         /// Creates the triggers that define when the task will run.
         /// </summary>
         /// </summary>
         /// <returns>IEnumerable{BaseTaskTrigger}.</returns>
         /// <returns>IEnumerable{BaseTaskTrigger}.</returns>
         public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
         public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
         {
         {
-            return new[] {
+            return new[]
+            {
                 new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks}
                 new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks}
             };
             };
         }
         }
@@ -57,10 +78,10 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
         public Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
         public Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
         {
         {
             // Delete log files more than n days old
             // Delete log files more than n days old
-            var minDateModified = DateTime.UtcNow.AddDays(-ConfigurationManager.CommonConfiguration.LogFileRetentionDays);
+            var minDateModified = DateTime.UtcNow.AddDays(-_configurationManager.CommonConfiguration.LogFileRetentionDays);
 
 
             // Only delete the .txt log files, the *.log files created by serilog get managed by itself
             // Only delete the .txt log files, the *.log files created by serilog get managed by itself
-            var filesToDelete = _fileSystem.GetFiles(ConfigurationManager.CommonApplicationPaths.LogDirectoryPath, new[] { ".txt" }, true, true)
+            var filesToDelete = _fileSystem.GetFiles(_configurationManager.CommonApplicationPaths.LogDirectoryPath, new[] { ".txt" }, true, true)
                           .Where(f => _fileSystem.GetLastWriteTimeUtc(f) < minDateModified)
                           .Where(f => _fileSystem.GetLastWriteTimeUtc(f) < minDateModified)
                           .ToList();
                           .ToList();
 
 
@@ -83,26 +104,5 @@ namespace Emby.Server.Implementations.ScheduledTasks.Tasks
 
 
             return Task.CompletedTask;
             return Task.CompletedTask;
         }
         }
-
-        /// <inheritdoc />
-        public string Name => _localization.GetLocalizedString("TaskCleanLogs");
-
-        /// <inheritdoc />
-        public string Description => string.Format(_localization.GetLocalizedString("TaskCleanLogsDescription"), ConfigurationManager.CommonConfiguration.LogFileRetentionDays);
-
-        /// <inheritdoc />
-        public string Category => _localization.GetLocalizedString("TasksMaintenanceCategory");
-
-        /// <inheritdoc />
-        public string Key => "CleanLogFiles";
-
-        /// <inheritdoc />
-        public bool IsHidden => false;
-
-        /// <inheritdoc />
-        public bool IsEnabled => true;
-
-        /// <inheritdoc />
-        public bool IsLogged => true;
     }
     }
 }
 }

+ 4 - 4
Emby.Server.Implementations/Services/ServicePath.cs

@@ -80,8 +80,8 @@ namespace Emby.Server.Implementations.Services
 
 
         public static List<string> GetFirstMatchWildCardHashKeys(string[] pathPartsForMatching)
         public static List<string> GetFirstMatchWildCardHashKeys(string[] pathPartsForMatching)
         {
         {
-            const string hashPrefix = WildCard + PathSeperator;
-            return GetPotentialMatchesWithPrefix(hashPrefix, pathPartsForMatching);
+            const string HashPrefix = WildCard + PathSeperator;
+            return GetPotentialMatchesWithPrefix(HashPrefix, pathPartsForMatching);
         }
         }
 
 
         private static List<string> GetPotentialMatchesWithPrefix(string hashPrefix, string[] pathPartsForMatching)
         private static List<string> GetPotentialMatchesWithPrefix(string hashPrefix, string[] pathPartsForMatching)
@@ -92,7 +92,7 @@ namespace Emby.Server.Implementations.Services
             {
             {
                 list.Add(hashPrefix + part);
                 list.Add(hashPrefix + part);
 
 
-                if (part.IndexOf(ComponentSeperator) == -1)
+                if (part.IndexOf(ComponentSeperator, StringComparison.Ordinal) == -1)
                 {
                 {
                     continue;
                     continue;
                 }
                 }
@@ -130,7 +130,7 @@ namespace Emby.Server.Implementations.Services
                 }
                 }
 
 
                 if (component.IndexOf(VariablePrefix, StringComparison.OrdinalIgnoreCase) != -1
                 if (component.IndexOf(VariablePrefix, StringComparison.OrdinalIgnoreCase) != -1
-                    && component.IndexOf(ComponentSeperator) != -1)
+                    && component.IndexOf(ComponentSeperator, StringComparison.Ordinal) != -1)
                 {
                 {
                     hasSeparators.Add(true);
                     hasSeparators.Add(true);
                     componentsList.AddRange(component.Split(ComponentSeperator));
                     componentsList.AddRange(component.Split(ComponentSeperator));

+ 0 - 1
MediaBrowser.Controller/Entities/UserViewBuilder.cs

@@ -10,7 +10,6 @@ using MediaBrowser.Controller.Configuration;
 using MediaBrowser.Controller.Entities.Movies;
 using MediaBrowser.Controller.Entities.Movies;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.TV;
 using MediaBrowser.Controller.TV;
-using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Querying;
 using MediaBrowser.Model.Querying;
 using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.Logging;

+ 2 - 2
MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs

@@ -240,11 +240,11 @@ namespace MediaBrowser.MediaEncoding.Attachments
             if (protocol == MediaProtocol.File)
             if (protocol == MediaProtocol.File)
             {
             {
                 var date = _fileSystem.GetLastWriteTimeUtc(mediaPath);
                 var date = _fileSystem.GetLastWriteTimeUtc(mediaPath);
-                filename = (mediaPath + attachmentStreamIndex.ToString(CultureInfo.InvariantCulture) + "_" + date.Ticks.ToString(CultureInfo.InvariantCulture)).GetMD5().ToString("D");
+                filename = (mediaPath + attachmentStreamIndex.ToString(CultureInfo.InvariantCulture) + "_" + date.Ticks.ToString(CultureInfo.InvariantCulture)).GetMD5().ToString("D", CultureInfo.InvariantCulture);
             }
             }
             else
             else
             {
             {
-                filename = (mediaPath + attachmentStreamIndex.ToString(CultureInfo.InvariantCulture)).GetMD5().ToString("D");
+                filename = (mediaPath + attachmentStreamIndex.ToString(CultureInfo.InvariantCulture)).GetMD5().ToString("D", CultureInfo.InvariantCulture);
             }
             }
 
 
             var prefix = filename.Substring(0, 1);
             var prefix = filename.Substring(0, 1);

+ 3 - 2
MediaBrowser.MediaEncoding/Encoder/EncodingUtils.cs

@@ -1,5 +1,6 @@
 #pragma warning disable CS1591
 #pragma warning disable CS1591
 
 
+using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Globalization;
 using System.Globalization;
 using System.Linq;
 using System.Linq;
@@ -48,7 +49,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
         /// <returns>System.String.</returns>
         /// <returns>System.String.</returns>
         private static string GetFileInputArgument(string path)
         private static string GetFileInputArgument(string path)
         {
         {
-            if (path.IndexOf("://") != -1)
+            if (path.IndexOf("://", StringComparison.Ordinal) != -1)
             {
             {
                 return string.Format(CultureInfo.InvariantCulture, "\"{0}\"", path);
                 return string.Format(CultureInfo.InvariantCulture, "\"{0}\"", path);
             }
             }
@@ -67,7 +68,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
         private static string NormalizePath(string path)
         private static string NormalizePath(string path)
         {
         {
             // Quotes are valid path characters in linux and they need to be escaped here with a leading \
             // Quotes are valid path characters in linux and they need to be escaped here with a leading \
-            return path.Replace("\"", "\\\"");
+            return path.Replace("\"", "\\\"", StringComparison.Ordinal);
         }
         }
     }
     }
 }
 }

+ 2 - 2
MediaBrowser.MediaEncoding/Encoder/MediaEncoder.cs

@@ -374,7 +374,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
             var args = extractChapters
             var args = extractChapters
                 ? "{0} -i {1} -threads 0 -v warning -print_format json -show_streams -show_chapters -show_format"
                 ? "{0} -i {1} -threads 0 -v warning -print_format json -show_streams -show_chapters -show_format"
                 : "{0} -i {1} -threads 0 -v warning -print_format json -show_streams -show_format";
                 : "{0} -i {1} -threads 0 -v warning -print_format json -show_streams -show_format";
-            args = string.Format(args, probeSizeArgument, inputPath).Trim();
+            args = string.Format(CultureInfo.InvariantCulture, args, probeSizeArgument, inputPath).Trim();
 
 
             var process = new Process
             var process = new Process
             {
             {
@@ -853,7 +853,7 @@ namespace MediaBrowser.MediaEncoding.Encoder
             // https://ffmpeg.org/ffmpeg-filters.html#Notes-on-filtergraph-escaping
             // https://ffmpeg.org/ffmpeg-filters.html#Notes-on-filtergraph-escaping
             // We need to double escape
             // We need to double escape
 
 
-            return path.Replace('\\', '/').Replace(":", "\\:").Replace("'", "'\\\\\\''");
+            return path.Replace('\\', '/').Replace(":", "\\:", StringComparison.Ordinal).Replace("'", "'\\\\\\''", StringComparison.Ordinal);
         }
         }
 
 
         /// <inheritdoc />
         /// <inheritdoc />

+ 1 - 1
MediaBrowser.MediaEncoding/MediaBrowser.MediaEncoding.csproj

@@ -34,7 +34,7 @@
 
 
   <!-- Code Analyzers-->
   <!-- Code Analyzers-->
   <ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
   <ItemGroup Condition=" '$(Configuration)' == 'Debug' ">
-    <!-- <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8" PrivateAssets="All" /> -->
+    <PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.9.8" PrivateAssets="All" />
     <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
     <PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
     <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
     <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
     <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
     <PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />

+ 5 - 4
MediaBrowser.MediaEncoding/Probing/ProbeResultNormalizer.cs

@@ -42,7 +42,8 @@ namespace MediaBrowser.MediaEncoding.Probing
             var info = new MediaInfo
             var info = new MediaInfo
             {
             {
                 Path = path,
                 Path = path,
-                Protocol = protocol
+                Protocol = protocol,
+                VideoType = videoType
             };
             };
 
 
             FFProbeHelpers.NormalizeFFProbeResult(data);
             FFProbeHelpers.NormalizeFFProbeResult(data);
@@ -1133,7 +1134,7 @@ namespace MediaBrowser.MediaEncoding.Probing
         {
         {
             // Only use the comma as a delimeter if there are no slashes or pipes.
             // Only use the comma as a delimeter if there are no slashes or pipes.
             // We want to be careful not to split names that have commas in them
             // We want to be careful not to split names that have commas in them
-            var delimeter = !allowCommaDelimiter || _nameDelimiters.Any(i => val.IndexOf(i) != -1) ?
+            var delimeter = !allowCommaDelimiter || _nameDelimiters.Any(i => val.IndexOf(i, StringComparison.Ordinal) != -1) ?
                 _nameDelimiters :
                 _nameDelimiters :
                 new[] { ',' };
                 new[] { ',' };
 
 
@@ -1377,8 +1378,8 @@ namespace MediaBrowser.MediaEncoding.Probing
                         if (subtitle.Contains('/', StringComparison.Ordinal)) // It contains a episode number and season number
                         if (subtitle.Contains('/', StringComparison.Ordinal)) // It contains a episode number and season number
                         {
                         {
                             string[] numbers = subtitle.Split(' ');
                             string[] numbers = subtitle.Split(' ');
-                            video.IndexNumber = int.Parse(numbers[0].Replace(".", string.Empty, StringComparison.Ordinal).Split('/')[0]);
-                            int totalEpisodesInSeason = int.Parse(numbers[0].Replace(".", string.Empty, StringComparison.Ordinal).Split('/')[1]);
+                            video.IndexNumber = int.Parse(numbers[0].Replace(".", string.Empty, StringComparison.Ordinal).Split('/')[0], CultureInfo.InvariantCulture);
+                            int totalEpisodesInSeason = int.Parse(numbers[0].Replace(".", string.Empty, StringComparison.Ordinal).Split('/')[1], CultureInfo.InvariantCulture);
 
 
                             description = string.Join(" ", numbers, 1, numbers.Length - 1).Trim(); // Skip the first, concatenate the rest, clean up spaces and save it
                             description = string.Join(" ", numbers, 1, numbers.Length - 1).Trim(); // Skip the first, concatenate the rest, clean up spaces and save it
                         }
                         }

+ 4 - 4
MediaBrowser.MediaEncoding/Subtitles/AssParser.cs

@@ -86,9 +86,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles
 
 
         private void RemoteNativeFormatting(SubtitleTrackEvent p)
         private void RemoteNativeFormatting(SubtitleTrackEvent p)
         {
         {
-            int indexOfBegin = p.Text.IndexOf('{');
+            int indexOfBegin = p.Text.IndexOf('{', StringComparison.Ordinal);
             string pre = string.Empty;
             string pre = string.Empty;
-            while (indexOfBegin >= 0 && p.Text.IndexOf('}') > indexOfBegin)
+            while (indexOfBegin >= 0 && p.Text.IndexOf('}', StringComparison.Ordinal) > indexOfBegin)
             {
             {
                 string s = p.Text.Substring(indexOfBegin);
                 string s = p.Text.Substring(indexOfBegin);
                 if (s.StartsWith("{\\an1}", StringComparison.Ordinal) ||
                 if (s.StartsWith("{\\an1}", StringComparison.Ordinal) ||
@@ -116,10 +116,10 @@ namespace MediaBrowser.MediaEncoding.Subtitles
                     pre = s.Substring(0, 5) + "}";
                     pre = s.Substring(0, 5) + "}";
                 }
                 }
 
 
-                int indexOfEnd = p.Text.IndexOf('}');
+                int indexOfEnd = p.Text.IndexOf('}', StringComparison.Ordinal);
                 p.Text = p.Text.Remove(indexOfBegin, (indexOfEnd - indexOfBegin) + 1);
                 p.Text = p.Text.Remove(indexOfBegin, (indexOfEnd - indexOfBegin) + 1);
 
 
-                indexOfBegin = p.Text.IndexOf('{');
+                indexOfBegin = p.Text.IndexOf('{', StringComparison.Ordinal);
             }
             }
 
 
             p.Text = pre + p.Text;
             p.Text = pre + p.Text;

+ 48 - 47
MediaBrowser.MediaEncoding/Subtitles/SsaParser.cs

@@ -1,5 +1,6 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.Globalization;
 using System.IO;
 using System.IO;
 using System.Text;
 using System.Text;
 using System.Threading;
 using System.Threading;
@@ -50,14 +51,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles
                     {
                     {
                         eventsStarted = true;
                         eventsStarted = true;
                     }
                     }
-                    else if (!string.IsNullOrEmpty(line) && line.Trim().StartsWith(";"))
+                    else if (!string.IsNullOrEmpty(line) && line.Trim().StartsWith(";", StringComparison.Ordinal))
                     {
                     {
                         // skip comment lines
                         // skip comment lines
                     }
                     }
                     else if (eventsStarted && line.Trim().Length > 0)
                     else if (eventsStarted && line.Trim().Length > 0)
                     {
                     {
                         string s = line.Trim().ToLowerInvariant();
                         string s = line.Trim().ToLowerInvariant();
-                        if (s.StartsWith("format:"))
+                        if (s.StartsWith("format:", StringComparison.Ordinal))
                         {
                         {
                             if (line.Length > 10)
                             if (line.Length > 10)
                             {
                             {
@@ -103,7 +104,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
 
 
                             string[] splittedLine;
                             string[] splittedLine;
 
 
-                            if (s.StartsWith("dialogue:"))
+                            if (s.StartsWith("dialogue:", StringComparison.Ordinal))
                             {
                             {
                                 splittedLine = line.Substring(10).Split(',');
                                 splittedLine = line.Substring(10).Split(',');
                             }
                             }
@@ -181,10 +182,10 @@ namespace MediaBrowser.MediaEncoding.Subtitles
             string[] timeCode = time.Split(':', '.');
             string[] timeCode = time.Split(':', '.');
             return new TimeSpan(
             return new TimeSpan(
                 0,
                 0,
-                int.Parse(timeCode[0]),
-                int.Parse(timeCode[1]),
-                int.Parse(timeCode[2]),
-                int.Parse(timeCode[3]) * 10).Ticks;
+                int.Parse(timeCode[0], CultureInfo.InvariantCulture),
+                int.Parse(timeCode[1], CultureInfo.InvariantCulture),
+                int.Parse(timeCode[2], CultureInfo.InvariantCulture),
+                int.Parse(timeCode[3], CultureInfo.InvariantCulture) * 10).Ticks;
         }
         }
 
 
         private static string GetFormattedText(string text)
         private static string GetFormattedText(string text)
@@ -193,11 +194,11 @@ namespace MediaBrowser.MediaEncoding.Subtitles
 
 
             for (int i = 0; i < 10; i++) // just look ten times...
             for (int i = 0; i < 10; i++) // just look ten times...
             {
             {
-                if (text.Contains(@"{\fn"))
+                if (text.Contains(@"{\fn", StringComparison.Ordinal))
                 {
                 {
-                    int start = text.IndexOf(@"{\fn");
+                    int start = text.IndexOf(@"{\fn", StringComparison.Ordinal);
                     int end = text.IndexOf('}', start);
                     int end = text.IndexOf('}', start);
-                    if (end > 0 && !text.Substring(start).StartsWith("{\\fn}"))
+                    if (end > 0 && !text.Substring(start).StartsWith("{\\fn}", StringComparison.Ordinal))
                     {
                     {
                         string fontName = text.Substring(start + 4, end - (start + 4));
                         string fontName = text.Substring(start + 4, end - (start + 4));
                         string extraTags = string.Empty;
                         string extraTags = string.Empty;
@@ -212,7 +213,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
                             text = text.Insert(start, "<font face=\"" + fontName + "\"" + extraTags + ">");
                             text = text.Insert(start, "<font face=\"" + fontName + "\"" + extraTags + ">");
                         }
                         }
 
 
-                        int indexOfEndTag = text.IndexOf("{\\fn}", start);
+                        int indexOfEndTag = text.IndexOf("{\\fn}", start, StringComparison.Ordinal);
                         if (indexOfEndTag > 0)
                         if (indexOfEndTag > 0)
                         {
                         {
                             text = text.Remove(indexOfEndTag, "{\\fn}".Length).Insert(indexOfEndTag, "</font>");
                             text = text.Remove(indexOfEndTag, "{\\fn}".Length).Insert(indexOfEndTag, "</font>");
@@ -224,11 +225,11 @@ namespace MediaBrowser.MediaEncoding.Subtitles
                     }
                     }
                 }
                 }
 
 
-                if (text.Contains(@"{\fs"))
+                if (text.Contains(@"{\fs", StringComparison.Ordinal))
                 {
                 {
-                    int start = text.IndexOf(@"{\fs");
+                    int start = text.IndexOf(@"{\fs", StringComparison.Ordinal);
                     int end = text.IndexOf('}', start);
                     int end = text.IndexOf('}', start);
-                    if (end > 0 && !text.Substring(start).StartsWith("{\\fs}"))
+                    if (end > 0 && !text.Substring(start).StartsWith("{\\fs}", StringComparison.Ordinal))
                     {
                     {
                         string fontSize = text.Substring(start + 4, end - (start + 4));
                         string fontSize = text.Substring(start + 4, end - (start + 4));
                         string extraTags = string.Empty;
                         string extraTags = string.Empty;
@@ -245,7 +246,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
                                 text = text.Insert(start, "<font size=\"" + fontSize + "\"" + extraTags + ">");
                                 text = text.Insert(start, "<font size=\"" + fontSize + "\"" + extraTags + ">");
                             }
                             }
 
 
-                            int indexOfEndTag = text.IndexOf("{\\fs}", start);
+                            int indexOfEndTag = text.IndexOf("{\\fs}", start, StringComparison.Ordinal);
                             if (indexOfEndTag > 0)
                             if (indexOfEndTag > 0)
                             {
                             {
                                 text = text.Remove(indexOfEndTag, "{\\fs}".Length).Insert(indexOfEndTag, "</font>");
                                 text = text.Remove(indexOfEndTag, "{\\fs}".Length).Insert(indexOfEndTag, "</font>");
@@ -258,17 +259,17 @@ namespace MediaBrowser.MediaEncoding.Subtitles
                     }
                     }
                 }
                 }
 
 
-                if (text.Contains(@"{\c"))
+                if (text.Contains(@"{\c", StringComparison.Ordinal))
                 {
                 {
-                    int start = text.IndexOf(@"{\c");
+                    int start = text.IndexOf(@"{\c", StringComparison.Ordinal);
                     int end = text.IndexOf('}', start);
                     int end = text.IndexOf('}', start);
-                    if (end > 0 && !text.Substring(start).StartsWith("{\\c}"))
+                    if (end > 0 && !text.Substring(start).StartsWith("{\\c}", StringComparison.Ordinal))
                     {
                     {
                         string color = text.Substring(start + 4, end - (start + 4));
                         string color = text.Substring(start + 4, end - (start + 4));
                         string extraTags = string.Empty;
                         string extraTags = string.Empty;
                         CheckAndAddSubTags(ref color, ref extraTags, out bool italic);
                         CheckAndAddSubTags(ref color, ref extraTags, out bool italic);
 
 
-                        color = color.Replace("&", string.Empty).TrimStart('H');
+                        color = color.Replace("&", string.Empty, StringComparison.Ordinal).TrimStart('H');
                         color = color.PadLeft(6, '0');
                         color = color.PadLeft(6, '0');
 
 
                         // switch to rrggbb from bbggrr
                         // switch to rrggbb from bbggrr
@@ -285,7 +286,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
                             text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + ">");
                             text = text.Insert(start, "<font color=\"" + color + "\"" + extraTags + ">");
                         }
                         }
 
 
-                        int indexOfEndTag = text.IndexOf("{\\c}", start);
+                        int indexOfEndTag = text.IndexOf("{\\c}", start, StringComparison.Ordinal);
                         if (indexOfEndTag > 0)
                         if (indexOfEndTag > 0)
                         {
                         {
                             text = text.Remove(indexOfEndTag, "{\\c}".Length).Insert(indexOfEndTag, "</font>");
                             text = text.Remove(indexOfEndTag, "{\\c}".Length).Insert(indexOfEndTag, "</font>");
@@ -297,17 +298,17 @@ namespace MediaBrowser.MediaEncoding.Subtitles
                     }
                     }
                 }
                 }
 
 
-                if (text.Contains(@"{\1c")) // "1" specifices primary color
+                if (text.Contains(@"{\1c", StringComparison.Ordinal)) // "1" specifices primary color
                 {
                 {
-                    int start = text.IndexOf(@"{\1c");
+                    int start = text.IndexOf(@"{\1c", StringComparison.Ordinal);
                     int end = text.IndexOf('}', start);
                     int end = text.IndexOf('}', start);
-                    if (end > 0 && !text.Substring(start).StartsWith("{\\1c}"))
+                    if (end > 0 && !text.Substring(start).StartsWith("{\\1c}", StringComparison.Ordinal))
                     {
                     {
                         string color = text.Substring(start + 5, end - (start + 5));
                         string color = text.Substring(start + 5, end - (start + 5));
                         string extraTags = string.Empty;
                         string extraTags = string.Empty;
                         CheckAndAddSubTags(ref color, ref extraTags, out bool italic);
                         CheckAndAddSubTags(ref color, ref extraTags, out bool italic);
 
 
-                        color = color.Replace("&", string.Empty).TrimStart('H');
+                        color = color.Replace("&", string.Empty, StringComparison.Ordinal).TrimStart('H');
                         color = color.PadLeft(6, '0');
                         color = color.PadLeft(6, '0');
 
 
                         // switch to rrggbb from bbggrr
                         // switch to rrggbb from bbggrr
@@ -329,25 +330,25 @@ namespace MediaBrowser.MediaEncoding.Subtitles
                 }
                 }
             }
             }
 
 
-            text = text.Replace(@"{\i1}", "<i>");
-            text = text.Replace(@"{\i0}", "</i>");
-            text = text.Replace(@"{\i}", "</i>");
+            text = text.Replace(@"{\i1}", "<i>", StringComparison.Ordinal);
+            text = text.Replace(@"{\i0}", "</i>", StringComparison.Ordinal);
+            text = text.Replace(@"{\i}", "</i>", StringComparison.Ordinal);
             if (CountTagInText(text, "<i>") > CountTagInText(text, "</i>"))
             if (CountTagInText(text, "<i>") > CountTagInText(text, "</i>"))
             {
             {
                 text += "</i>";
                 text += "</i>";
             }
             }
 
 
-            text = text.Replace(@"{\u1}", "<u>");
-            text = text.Replace(@"{\u0}", "</u>");
-            text = text.Replace(@"{\u}", "</u>");
+            text = text.Replace(@"{\u1}", "<u>", StringComparison.Ordinal);
+            text = text.Replace(@"{\u0}", "</u>", StringComparison.Ordinal);
+            text = text.Replace(@"{\u}", "</u>", StringComparison.Ordinal);
             if (CountTagInText(text, "<u>") > CountTagInText(text, "</u>"))
             if (CountTagInText(text, "<u>") > CountTagInText(text, "</u>"))
             {
             {
                 text += "</u>";
                 text += "</u>";
             }
             }
 
 
-            text = text.Replace(@"{\b1}", "<b>");
-            text = text.Replace(@"{\b0}", "</b>");
-            text = text.Replace(@"{\b}", "</b>");
+            text = text.Replace(@"{\b1}", "<b>", StringComparison.Ordinal);
+            text = text.Replace(@"{\b0}", "</b>", StringComparison.Ordinal);
+            text = text.Replace(@"{\b}", "</b>", StringComparison.Ordinal);
             if (CountTagInText(text, "<b>") > CountTagInText(text, "</b>"))
             if (CountTagInText(text, "<b>") > CountTagInText(text, "</b>"))
             {
             {
                 text += "</b>";
                 text += "</b>";
@@ -362,7 +363,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
         private static int CountTagInText(string text, string tag)
         private static int CountTagInText(string text, string tag)
         {
         {
             int count = 0;
             int count = 0;
-            int index = text.IndexOf(tag);
+            int index = text.IndexOf(tag, StringComparison.Ordinal);
             while (index >= 0)
             while (index >= 0)
             {
             {
                 count++;
                 count++;
@@ -371,7 +372,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
                     return count;
                     return count;
                 }
                 }
 
 
-                index = text.IndexOf(tag, index + 1);
+                index = text.IndexOf(tag, index + 1, StringComparison.Ordinal);
             }
             }
 
 
             return count;
             return count;
@@ -380,7 +381,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
         private static void CheckAndAddSubTags(ref string tagName, ref string extraTags, out bool italic)
         private static void CheckAndAddSubTags(ref string tagName, ref string extraTags, out bool italic)
         {
         {
             italic = false;
             italic = false;
-            int indexOfSPlit = tagName.IndexOf(@"\");
+            int indexOfSPlit = tagName.IndexOf('\\', StringComparison.Ordinal);
             if (indexOfSPlit > 0)
             if (indexOfSPlit > 0)
             {
             {
                 string rest = tagName.Substring(indexOfSPlit).TrimStart('\\');
                 string rest = tagName.Substring(indexOfSPlit).TrimStart('\\');
@@ -388,9 +389,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles
 
 
                 for (int i = 0; i < 10; i++)
                 for (int i = 0; i < 10; i++)
                 {
                 {
-                    if (rest.StartsWith("fs") && rest.Length > 2)
+                    if (rest.StartsWith("fs", StringComparison.Ordinal) && rest.Length > 2)
                     {
                     {
-                        indexOfSPlit = rest.IndexOf(@"\");
+                        indexOfSPlit = rest.IndexOf('\\', StringComparison.Ordinal);
                         string fontSize = rest;
                         string fontSize = rest;
                         if (indexOfSPlit > 0)
                         if (indexOfSPlit > 0)
                         {
                         {
@@ -404,9 +405,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles
 
 
                         extraTags += " size=\"" + fontSize.Substring(2) + "\"";
                         extraTags += " size=\"" + fontSize.Substring(2) + "\"";
                     }
                     }
-                    else if (rest.StartsWith("fn") && rest.Length > 2)
+                    else if (rest.StartsWith("fn", StringComparison.Ordinal) && rest.Length > 2)
                     {
                     {
-                        indexOfSPlit = rest.IndexOf(@"\");
+                        indexOfSPlit = rest.IndexOf('\\', StringComparison.Ordinal);
                         string fontName = rest;
                         string fontName = rest;
                         if (indexOfSPlit > 0)
                         if (indexOfSPlit > 0)
                         {
                         {
@@ -420,9 +421,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles
 
 
                         extraTags += " face=\"" + fontName.Substring(2) + "\"";
                         extraTags += " face=\"" + fontName.Substring(2) + "\"";
                     }
                     }
-                    else if (rest.StartsWith("c") && rest.Length > 2)
+                    else if (rest.StartsWith("c", StringComparison.Ordinal) && rest.Length > 2)
                     {
                     {
-                        indexOfSPlit = rest.IndexOf(@"\");
+                        indexOfSPlit = rest.IndexOf('\\', StringComparison.Ordinal);
                         string fontColor = rest;
                         string fontColor = rest;
                         if (indexOfSPlit > 0)
                         if (indexOfSPlit > 0)
                         {
                         {
@@ -435,7 +436,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
                         }
                         }
 
 
                         string color = fontColor.Substring(2);
                         string color = fontColor.Substring(2);
-                        color = color.Replace("&", string.Empty).TrimStart('H');
+                        color = color.Replace("&", string.Empty, StringComparison.Ordinal).TrimStart('H');
                         color = color.PadLeft(6, '0');
                         color = color.PadLeft(6, '0');
                         // switch to rrggbb from bbggrr
                         // switch to rrggbb from bbggrr
                         color = "#" + color.Remove(color.Length - 6) + color.Substring(color.Length - 2, 2) + color.Substring(color.Length - 4, 2) + color.Substring(color.Length - 6, 2);
                         color = "#" + color.Remove(color.Length - 6) + color.Substring(color.Length - 2, 2) + color.Substring(color.Length - 4, 2) + color.Substring(color.Length - 6, 2);
@@ -443,9 +444,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles
 
 
                         extraTags += " color=\"" + color + "\"";
                         extraTags += " color=\"" + color + "\"";
                     }
                     }
-                    else if (rest.StartsWith("i1") && rest.Length > 1)
+                    else if (rest.StartsWith("i1", StringComparison.Ordinal) && rest.Length > 1)
                     {
                     {
-                        indexOfSPlit = rest.IndexOf(@"\");
+                        indexOfSPlit = rest.IndexOf('\\', StringComparison.Ordinal);
                         italic = true;
                         italic = true;
                         if (indexOfSPlit > 0)
                         if (indexOfSPlit > 0)
                         {
                         {
@@ -456,9 +457,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles
                             rest = string.Empty;
                             rest = string.Empty;
                         }
                         }
                     }
                     }
-                    else if (rest.Length > 0 && rest.Contains("\\"))
+                    else if (rest.Length > 0 && rest.Contains('\\', StringComparison.Ordinal))
                     {
                     {
-                        indexOfSPlit = rest.IndexOf(@"\");
+                        indexOfSPlit = rest.IndexOf('\\', StringComparison.Ordinal);
                         rest = rest.Substring(indexOfSPlit).TrimStart('\\');
                         rest = rest.Substring(indexOfSPlit).TrimStart('\\');
                     }
                     }
                 }
                 }

+ 9 - 8
MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs

@@ -415,7 +415,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
 
 
             // FFmpeg automatically convert character encoding when it is UTF-16
             // FFmpeg automatically convert character encoding when it is UTF-16
             // If we specify character encoding, it rejects with "do not specify a character encoding" and "Unable to recode subtitle event"
             // If we specify character encoding, it rejects with "do not specify a character encoding" and "Unable to recode subtitle event"
-            if ((inputPath.EndsWith(".smi") || inputPath.EndsWith(".sami")) &&
+            if ((inputPath.EndsWith(".smi", StringComparison.Ordinal) || inputPath.EndsWith(".sami", StringComparison.Ordinal)) &&
                 (encodingParam.Equals("UTF-16BE", StringComparison.OrdinalIgnoreCase) ||
                 (encodingParam.Equals("UTF-16BE", StringComparison.OrdinalIgnoreCase) ||
                  encodingParam.Equals("UTF-16LE", StringComparison.OrdinalIgnoreCase)))
                  encodingParam.Equals("UTF-16LE", StringComparison.OrdinalIgnoreCase)))
             {
             {
@@ -506,7 +506,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
                     string.Format(CultureInfo.InvariantCulture, "ffmpeg subtitle conversion failed for {0}", inputPath));
                     string.Format(CultureInfo.InvariantCulture, "ffmpeg subtitle conversion failed for {0}", inputPath));
             }
             }
 
 
-            await SetAssFont(outputPath).ConfigureAwait(false);
+            await SetAssFont(outputPath, cancellationToken).ConfigureAwait(false);
 
 
             _logger.LogInformation("ffmpeg subtitle conversion succeeded for {Path}", inputPath);
             _logger.LogInformation("ffmpeg subtitle conversion succeeded for {Path}", inputPath);
         }
         }
@@ -668,7 +668,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
 
 
             if (string.Equals(outputCodec, "ass", StringComparison.OrdinalIgnoreCase))
             if (string.Equals(outputCodec, "ass", StringComparison.OrdinalIgnoreCase))
             {
             {
-                await SetAssFont(outputPath).ConfigureAwait(false);
+                await SetAssFont(outputPath, cancellationToken).ConfigureAwait(false);
             }
             }
         }
         }
 
 
@@ -676,8 +676,9 @@ namespace MediaBrowser.MediaEncoding.Subtitles
         /// Sets the ass font.
         /// Sets the ass font.
         /// </summary>
         /// </summary>
         /// <param name="file">The file.</param>
         /// <param name="file">The file.</param>
+        /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is <c>System.Threading.CancellationToken.None</c>.</param>
         /// <returns>Task.</returns>
         /// <returns>Task.</returns>
-        private async Task SetAssFont(string file)
+        private async Task SetAssFont(string file, CancellationToken cancellationToken = default)
         {
         {
             _logger.LogInformation("Setting ass font within {File}", file);
             _logger.LogInformation("Setting ass font within {File}", file);
 
 
@@ -692,14 +693,14 @@ namespace MediaBrowser.MediaEncoding.Subtitles
                 text = await reader.ReadToEndAsync().ConfigureAwait(false);
                 text = await reader.ReadToEndAsync().ConfigureAwait(false);
             }
             }
 
 
-            var newText = text.Replace(",Arial,", ",Arial Unicode MS,");
+            var newText = text.Replace(",Arial,", ",Arial Unicode MS,", StringComparison.Ordinal);
 
 
-            if (!string.Equals(text, newText))
+            if (!string.Equals(text, newText, StringComparison.Ordinal))
             {
             {
                 using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read))
                 using (var fileStream = new FileStream(file, FileMode.Create, FileAccess.Write, FileShare.Read))
                 using (var writer = new StreamWriter(fileStream, encoding))
                 using (var writer = new StreamWriter(fileStream, encoding))
                 {
                 {
-                    writer.Write(newText);
+                    await writer.WriteAsync(newText.AsMemory(), cancellationToken).ConfigureAwait(false);
                 }
                 }
             }
             }
         }
         }
@@ -736,7 +737,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles
                 var charset = CharsetDetector.DetectFromStream(stream).Detected?.EncodingName;
                 var charset = CharsetDetector.DetectFromStream(stream).Detected?.EncodingName;
 
 
                 // UTF16 is automatically converted to UTF8 by FFmpeg, do not specify a character encoding
                 // UTF16 is automatically converted to UTF8 by FFmpeg, do not specify a character encoding
-                if ((path.EndsWith(".ass") || path.EndsWith(".ssa") || path.EndsWith(".srt"))
+                if ((path.EndsWith(".ass", StringComparison.Ordinal) || path.EndsWith(".ssa", StringComparison.Ordinal) || path.EndsWith(".srt", StringComparison.Ordinal))
                     && (string.Equals(charset, "utf-16le", StringComparison.OrdinalIgnoreCase)
                     && (string.Equals(charset, "utf-16le", StringComparison.OrdinalIgnoreCase)
                         || string.Equals(charset, "utf-16be", StringComparison.OrdinalIgnoreCase)))
                         || string.Equals(charset, "utf-16be", StringComparison.OrdinalIgnoreCase)))
                 {
                 {